我有一个要在HTML表格中显示的项目列表。这个清单有"漏洞"但是,需要填写它才能正确显示(x
和y
是表格中的列和行)。我无法弄清楚在哪里开始这样做。
<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>
如何填充列表看起来像这样?保证订购物品,我知道每个轴上有多少物品。
编辑:我没有意识到问题可能被解释为我想要一个简单的列表。每个项目中都有其他数据,这使得保留现有项目节点变得非常重要。所以我需要的是一种只创建填充节点并将现有节点保持原样的方法。为了创建一个演示我的问题的最小例子,我有点过分了。对不起。
答案 0 :(得分:2)
如果您的示例与实际数据一样简单,您应该能够使用递归模板调用来检查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>
答案 1 :(得分:1)
我知道每个轴上有多少项。
假设您可以将这些知识作为参数传递给样式表,我建议您这样做:
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 <= $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 <= $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"/>
为:
<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
值作为表格尺寸。
答案 2 :(得分:0)
您可以使用以下XSLT实现此目的。这是一种特殊的解决方案,但是通过使用命名空间的XML岛创建'count'变量是一种非常通用的方法,用于模拟具有固定计数的'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>
输出符合要求。