【问题标题】:Is there any way to group non child elements in xslt?有没有办法在 xslt 中对非子元素进行分组?
【发布时间】:2017-02-08 03:47:29
【问题描述】:

我有一个具有以下树结构的 xml 文件:

<foo attr1=""/>
<foo2 num="1"/>
<foo2 num="2"/>
<foo2 num="3"/>
<foo2 num="4"/>
<foo attr1=""/>
<foo2 num="1"/>
...

如您所见,元素 foo2 不是 foo 的子元素,但我想 将 foo2 num="1" thru num="4" 与第一个 foo 出现分组。没有 其中没有一个我可以用作参考的属性...

有什么方法可以用 xsl 实现这一点吗?

我已经成功地轻松地遍历了所有 foo 的出现(使用 xsl:for-each 属性),但棘手的部分是为每个 foo 循环包含以下 foo2 元素。

编辑: 让我们假设 attr 有一个随机值,例如:

<foo attr1="abc"/>
<foo2 num="1"/>
<foo2 num="2"/>
<foo2 num="3"/>
<foo2 num="4"/>
<foo attr1="def"/>
<foo2 num="1"/>

我想要做的是将 abc 和以下 foo 组合在一个表中,以便:

+--------+-----+
| abc    | def |
| 1      |   1 |
| 2      |     |
| 3      |     |
| 4      |     |
+--------------+

不,很遗憾它不支持 xslt 2.0。

【问题讨论】:

  • 1. 您的问题并不完全清楚。请向我们展示预期的输出。 2. 您的处理器是否支持 XSLT 2.0?
  • @michael.hor257k 我刚​​刚更新了我的帖子。

标签: xml xslt


【解决方案1】:

这里有两个不同的问题:

  1. 如何使用等效于 XSLT 2.0 的 group-starting-with 对节点进行分组;

  2. 如何转置(透视)结果,以便您可以构建一个表格,其中每个组占据一个 - 即使 HTML 表格是逐行构造的

我建议你分两次这样做:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="grp" match="foo2" use="generate-id(preceding-sibling::foo[1])" />

<!-- first-pass -->
<xsl:variable name="groups-rtf">
    <xsl:for-each select="root/foo">
        <group name="{@attr1}">
            <xsl:for-each select="key('grp', generate-id())">
                <item><xsl:value-of select="@num"/></item>
            </xsl:for-each>
        </group>
    </xsl:for-each>
</xsl:variable>
<xsl:variable name="groups" select="exsl:node-set($groups-rtf)/group" />

<xsl:template match="/">
    <table border="1">
        <!-- header row -->
        <tr>
            <xsl:for-each select="$groups">
                <th><xsl:value-of select="@name"/></th>
            </xsl:for-each>
        </tr>       
        <!-- data rows -->
        <xsl:call-template name="generate-rows"/>
    </table>
</xsl:template>

<xsl:template name="generate-rows">
    <xsl:param name="i" select="1"/>
    <xsl:if test="$groups/item[$i]">
        <tr>
            <xsl:for-each select="$groups">
                <td><xsl:value-of select="item[$i]"/></td>
            </xsl:for-each>
        </tr>
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="i" select="$i + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

应用于以下示例输入:

XML

<root>
    <foo attr1="abc"/>
    <foo2 num="1"/>
    <foo2 num="2"/>
    <foo2 num="3"/>
    <foo2 num="4"/>
    <foo attr1="def"/>
    <foo2 num="5"/>
    <foo2 num="6"/>
</root>

(渲染的)结果将是:

【讨论】:

    猜你喜欢
    • 2011-02-26
    • 1970-01-01
    • 2012-11-24
    • 2019-03-04
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多