如何使用XSLT 1.0填写XML列表中的孔



我有一个要在HTML表中显示的项目列表。不过,该列表具有"孔",需要填写才能正确显示(xy是表中的列和行)。我什至无法弄清楚在哪里可以做到这一点。

<items>
  <row y="1">
    <item x="1" y="1" data="importantStuff1"/>
  </row>
  <row y="2">
    <item x="2" y="2" data="importantStuff3"/>
  </row>
  <row y="3">
    <item x="5" y="3" data="importantStuff1"/>
  </row>
  <row y="4">
    <item x="3" y="4" data="importantStuff2"/>
    <item x="4" y="4" data="importantStuff3"/>
  </row>
</items>

我需要的是以下内容:

<items>
  <row y="1">
    <item x="1" y="1" data="importantStuff1"/>
    <item x="2" y="1" data="padding"/>
    <item x="3" y="1" data="padding"/>
    <item x="4" y="1" data="padding"/>
    <item x="5" y="1" data="padding"/>
  </row>
  <row y="2">
    <item x="1" y="2" data="padding"/>
    <item x="2" y="2" data="importantStuff3"/>
    <item x="3" y="2" data="padding"/>
    <item x="4" y="2" data="padding"/>
    <item x="5" y="2" data="padding"/>
  </row>
  <row y="3">
    <item x="1" y="3" data="padding"/>
    <item x="2" y="3" data="padding"/>
    <item x="3" y="3" data="padding"/>
    <item x="4" y="3" data="padding"/>
    <item x="5" y="3" data="importantStuff1"/>
  </row>
  <row y="4">
    <item x="1" y="4" data="padding"/>
    <item x="2" y="4" data="padding"/>
    <item x="3" y="4" data="importantStuff2"/>
    <item x="4" y="4" data="importantStuff3"/>
    <item x="5" y="4" data="padding"/>
  </row>
</items>

如何将列表添加到这样?保证这些项目被订购,我知道每个轴上有多少个项目。

编辑:我没有意识到这个问题可以解释为我想要一个简单的列表。每个项目中都有其他数据,使得保留现有项目节点很重要。因此,我需要的是一种仅创建填充节点并将现有节点留下的方法。

为了创建一个最小的示例来证明我的问题,我有点过分了。对此很抱歉。

如果您的示例与实际数据一样简单,则应使用递归模板调用来检查5个项目中的每一个。如果在那里,请对其进行申请。如果不是,请创建它。

示例...

XML输入

<items>
    <row y="1">
        <item x="1" y="1" data="importantStuff1"/>
    </row>
    <row y="2">
        <item x="2" y="2" data="importantStuff3"/>
    </row>
    <row y="3">
        <item x="5" y="3" data="importantStuff1"/>
    </row>
    <row y="4">
        <item x="3" y="4" data="importantStuff2"/>
        <item x="4" y="4" data="importantStuff3"/>
    </row>5
</items>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:param name="items" select="5"/>
  <!--Identity transform. Copy everything as-is unless overridden by
  a more specific template.--> 
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="row">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:call-template name="outputItems">
        <xsl:with-param name="count" select="1"/>
      </xsl:call-template>
    </xsl:copy>
  </xsl:template>
  <xsl:template name="outputItems">
    <xsl:param name="count"/>
    <xsl:choose>
      <!--Item already exists.-->
      <xsl:when test="item[@x=$count]">
        <xsl:apply-templates select="item[@x=$count]"/>
      </xsl:when>
      <!--Item does not exist. create it.-->
      <xsl:otherwise>
        <item x="{$count}" y="{@y}" data="padding"/>
      </xsl:otherwise>
    </xsl:choose>
    <!--Call this template again if needed.-->
    <xsl:if test="$items > $count">
      <xsl:call-template name="outputItems">
        <xsl:with-param name="count" select="$count + 1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

输出

<items>
   <row y="1">
      <item x="1" y="1" data="importantStuff1"/>
      <item x="2" y="1" data="padding"/>
      <item x="3" y="1" data="padding"/>
      <item x="4" y="1" data="padding"/>
      <item x="5" y="1" data="padding"/>
   </row>
   <row y="2">
      <item x="1" y="2" data="padding"/>
      <item x="2" y="2" data="importantStuff3"/>
      <item x="3" y="2" data="padding"/>
      <item x="4" y="2" data="padding"/>
      <item x="5" y="2" data="padding"/>
   </row>
   <row y="3">
      <item x="1" y="3" data="padding"/>
      <item x="2" y="3" data="padding"/>
      <item x="3" y="3" data="padding"/>
      <item x="4" y="3" data="padding"/>
      <item x="5" y="3" data="importantStuff1"/>
   </row>
   <row y="4">
      <item x="1" y="4" data="padding"/>
      <item x="2" y="4" data="padding"/>
      <item x="3" y="4" data="importantStuff2"/>
      <item x="4" y="4" data="importantStuff3"/>
      <item x="5" y="4" data="padding"/>
   </row>5
</items>

我知道每个轴上有多少个项目。

假设您可以将此知识作为参数传递给样式表,我建议您这样做:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="rows" select="4"/>
<xsl:param name="cols" select="5"/>
<xsl:key name="item" match="item" use="concat(@x, '|', @y)" />
<xsl:template match="/items">
    <xsl:copy>
        <xsl:call-template name="generate-rows"/>
    </xsl:copy>
</xsl:template>
<xsl:template name="generate-rows">
    <xsl:param name="y" select="1"/>
    <xsl:if test="$y &lt;= $rows">
        <row y="{$y}">
            <xsl:call-template name="generate-cols">
                <xsl:with-param name="y" select="$y"/>
            </xsl:call-template>
        </row>
        <!-- recursive call -->
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="y" select="$y + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>
<xsl:template name="generate-cols">
    <xsl:param name="y"/>
    <xsl:param name="x" select="1"/>
    <xsl:if test="$x &lt;= $cols">
         <item x="{$x}" y="{$y}" >
            <xsl:variable name="exisiting-item" select="key('item', concat($x, '|', $y))" />
            <xsl:attribute name="data">
                <xsl:choose>
                    <xsl:when test="$exisiting-item">
                        <xsl:value-of select="$exisiting-item/@data"/>
                    </xsl:when>
                    <xsl:otherwise>padding</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
        </item>
        <!-- recursive call -->
        <xsl:call-template name="generate-cols">
            <xsl:with-param name="y" select="$y"/>
            <xsl:with-param name="x" select="$x + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>
</xsl:stylesheet>

这将预先生成所提供的尺寸的表,并在每个单元格中填充来自相应项目的数据(如果存在)。

-

添加:

如果需要从输入中推导表尺寸,则更改:

<xsl:param name="rows" select="4"/>
<xsl:param name="cols" select="5"/>

to:

<xsl:variable name="rows" select="/items/row[last()]/@y"/>
<xsl:variable name="cols">
    <xsl:for-each select="/items/row/item">
        <xsl:sort select="@x" data-type="number" order="ascending"/>
        <xsl:if test="position()=last()">
            <xsl:value-of select="@x"/>
        </xsl:if>
    </xsl:for-each>
</xsl:variable>

这将最后一行的 y值和任何项目的最大 x值作为表尺寸。

您可以使用以下XSLT实现此目标。这是一种特殊的解决方案,但是使用名称XML岛创建"计数"变量是模仿固定计数的" For"循环的一种通用方法。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cnt="http://cnt.com" exclude-result-prefixes="cnt">
  <xsl:output method="xml" indent="yes" />
  <!-- creating a "count" XML structure -->
  <cnt:count>
    <x cnt="1" />
    <x cnt="2" />
    <x cnt="3" />
    <x cnt="4" />
    <x cnt="5" />
  </cnt:count>
  <xsl:template match="items">
    <items>
      <xsl:for-each select="row">
        <xsl:variable name="varY" select="@y" />   <!-- saving the value of '@y' -->
        <row y="{$varY}">
          <xsl:for-each select="document('')/xsl:stylesheet/cnt:count/x">
            <item x="{@cnt}" y="{$varY}" />
          </xsl:for-each>      
        </row>
      </xsl:for-each>      
    </items>
  </xsl:template>
</xsl:stylesheet>

输出是根据需要的。

相关内容

  • 没有找到相关文章

最新更新