我正在尝试将我的xml数据格式化为两个HTML表格。我成功地可以对一些虚拟数据xls进行排序:排序,但我不能将排序后的数据拆分成不同的表。
我的xml:
<a>
<b id="N">text1</b>
<b id="N">text2</b>
<b id="N+1">text3</b>
<b id="N">text4</b>
<b id="N+2">text5</b>
<b id="N+3">text6</b>
<b id="N">text7</b>
<b id="N+2">text8</b>
</a>
N在这种情况下是一个数字,但我不知道是哪个数字。它可以是2和55,3和4,44和52以及78和98.
我希望将每个号码发送到他们自己的表中,结果将是:
<table>
<tr><td>text1</td></tr>
<tr><td>text2</td></tr>
<tr><td>text4</td></tr>
<tr><td>text7</td></tr>
</table>
<table>
<tr><td>text3</td></tr>
</table>
<table>
<tr><td>text5</td></tr>
<tr><td>text8</td></tr>
</table>
<table>
<tr><td>text6</td></tr>
</table>
如何根据属性将排序后的数据分成不同的表?
任何指针都将不胜感激。
答案 0 :(得分:2)
XSLT 1.0中针对此类问题的标准方法称为 Muenchian分组。您可以定义一个键,以您希望的方式对目标元素进行分组
<xsl:key name="bsById" match="b" use="@id" />
然后使用generate-id
的技巧仅提取每个组中的第一个节点作为整个组的代理
<xsl:apply-templates select="b[generate-id()
= generate-id(key('bsById', @id)[1])]"
mode="group">
<xsl:sort select="@id" />
</xsl:apply-templates>
现在,每个组都会触发以下模板,您可以使用其中的key
函数来所有组中的节点
<xsl:template match="b" mode="group">
<table>
<!-- extract all the nodes that are grouped with this one -->
<xsl:apply-templates select="key('bsById', @id)">
<!-- you could <xsl:sort> here if you want to sort within groups -->
</xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="b">
<tr><td>...</td></tr>
</xsl:template>
如果该示例是您的整个XML文档,则上述所有内容都可以,但如果文档中有多个a
元素,每个元素都有自己的b
元素集,需要独立分组,那么关键需要更复杂。这里通常的技巧是使用父generate-id
节点的a
作为其b
子项的分组键值的一部分:
<xsl:key name="bsByParentAndId" match="a/b" use="concat(generate-id(..), '|', @id)" />
和Muenchian分组表达
<xsl:template match="a">
<xsl:apply-templates select="b[generate-id()
= generate-id(key('bsByParentAndId', concat(
generate-id(current()), '|', @id))[1])]"
mode="group"/>
</xsl:template>
对于记录,如果您可以使用XSLT 2.0,那么它变得非常容易。无需定义复杂的密钥,只需使用for-each-group
<xsl:template match="a">
<xsl:for-each-group select="b" group-by="@id">
<xsl:sort select="current-grouping-key()" />
<table>
<xsl:apply-templates select="current-group()" />
</table>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="b">
<tr><td>...</td></tr>
</xsl:template>