0

我正在尝试将我的 xml 数据格式化为两个 HTML 表。我可以成功地对一些虚拟数据 xls:sort 进行排序,但我无法将排序后的数据拆分到不同的表中。

我的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>

如何根据属性将排序后的数据分成不同的表?

任何指针将不胜感激。

4

1 回答 1

2

XSLT 1.0 中解决此类问题的标准方法称为Muenchian 分组。您定义一个键,以您想要的方式对您的目标元素进行分组

<xsl:key name="bsById" match="b" use="@id" />

然后使用技巧 withgenerate-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-ida节点的作为其子节点分组键值的一部分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>
于 2013-08-08T14:34:29.793 回答