xslt - 如何使用一些空属性进行 xslt Muenchian 分组?

标签 xslt xslt-1.0

与标准 Meunchain 分组略有不同,因为我正在处理一些正在转换的标签的 null(?) 属性。我希望将空分组视为它们自己的单独组,并使用转换后的输出添加分组字符串。另外,如果有一个分组来计算有多少人。

<root>
<section>
    <subsection>
        <module>
            <comp>111</comp>
        </module>
        <module group='group01'>
            <comp>222</comp>
        </module>
        <module group='group01'>
            <comp>333</comp>
        </module>
        <module>
            <comp>444</comp>
        </module>
        <module>
            <comp>555</comp>
        </module>
    </subsection>
</section>
<section>
    <subsection>
        <module group ="group02">
            <comp>666</comp>
        </module>
        <module group ="group02">
            <comp>777</comp>
        </module>
        <module>
            <comp>888</comp>
        </module>
        <module group ="group03">
            <comp>999</comp>
        </module>
        <module group ="group03">
            <comp>101010</comp>
        </module>
    </subsection>
    <subsection>
        <module group ="group04">
            <comp>11111</comp>
        </module>
        <module group ="group04">
            <comp>121212</comp>
        </module>
        <module group ="group05">
            <comp>131313</comp>
        </module>
        <module group ="group05">
            <comp>141414</comp>
        </module>
        <module group ="group06">
            <comp>151515</comp>
        </module>
        <module group ="group06">
            <comp>161616</comp>
        </module>
        <module>
            <comp>171717</comp>
        </module>
    </subsection>
</section>

想要的输出:

<AllSections>
<section>
    <subsection>
        <page>
            <content>111</content>
        </page>
        <page>
            <content>222333</content>
            <count>2</count>
        </page>
        <page>
            <content>444</content>
        </page>
        <page>
            <content>555</content>
        </page>
    </subsection>
</section>
<section>
    <subsection>
        <page>
            <content>666777</content>
            <count>2</count>
        </page>
        <page>
            <content>888</content>
        </page>
        <page>
            <content>999101010</content>
            <count>2</count>
        </page>
    </subsection>
    <subsection>
        <page>
            <content>111111121212</content>
            <count>2</count>
        </page>
        <page>
            <content>131313141414161616</content>
            <count>3</count>
        </page>
        <page>
            <content>151515</content>
        </page>
        <page>
            <content>171717</content>
        </page>
    </subsection>
</section>

谢谢!

最佳答案

对于具有 group 属性的元素,您将按该属性进行分组,但也在父 subsection 元素内进行分组。因此,您可以首先定义一个键来对它们进行分组,这是

<xsl:key name="modules" match="module[@group]" use="concat(generate-id(..), '|', @group)" />

接下来,您需要模板来匹配 module 元素的各种情况。首先,您可以有一个模板来匹配没有 group 属性的 module 元素,您可以在其中根据需要格式化输出。

<xsl:template match="module[not(@group)]">
    <page>
        <content>
            <xsl:value-of select="comp"/>
        </content>
    </page>
 </xsl:template>

对于具有 group 属性的模块,您需要一个匹配来检查此特定 module 元素是否在上面定义的键的组中第一个出现。

<xsl:template 
  match="module
    [@group]
    [generate-id() = generate-id(key('modules', concat(generate-id(..), '|', @group))[1])]">

在此模板中,您可以使用键轻松定义一个变量来保存组中的元素,然后输出子 comp 元素,或对它们进行计数

<xsl:variable name="modules" select="key('modules', concat(generate-id(..), '|', @group))"/>
<page>
    <content>
        <xsl:apply-templates select="$modules/comp/text()"/>
    </content>
    <count>
        <xsl:value-of select="count($modules)" />
     </count>
</page>

最后,您需要第三个模板来匹配所有其他 module 元素(即具有 group 属性的元素,但不是组中的第一个元素)以忽略它们,以确保他们不会获得两次输出。 (XSLT 处理器应该始终在这个更通用的模板之前匹配更具体的模板)

<xsl:template match="module"/>

这是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="modules" match="module[@group]" use="concat(generate-id(..), '|', @group)"/>

    <xsl:template match="root">
        <AllSections>
            <xsl:apply-templates />
        </AllSections>
    </xsl:template>

    <xsl:template match="module[not(@group)]">
        <page>
            <content>
                <xsl:value-of select="comp"/>
            </content>
        </page>
    </xsl:template>

    <xsl:template match="module[@group][generate-id() = generate-id(key('modules', concat(generate-id(..), '|', @group))[1])]">
        <xsl:variable name="modules" select="key('modules', concat(generate-id(..), '|', @group))"/>
        <page>
            <content>
                <xsl:apply-templates select="$modules/comp/text()"/>
            </content>
            <count>
                <xsl:value-of select="count($modules)" />
            </count>
        </page>
    </xsl:template>

    <xsl:template match="module"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

当应用于示例 XML 时,输出如下

<AllSections>
    <section>
        <subsection>
            <page>
                <content>111</content>
            </page>
            <page>
                <content>222333</content>
                <count>2</count>
            </page>
            <page>
                <content>444</content>
            </page>
            <page>
                <content>555</content>
            </page>
        </subsection>
    </section>
    <section>
        <subsection>
            <page>
                <content>666777</content>
                <count>2</count>
            </page>
            <page>
                <content>888</content>
            </page>
            <page>
                <content>999101010</content>
                <count>2</count>
            </page>
        </subsection>
        <subsection>
            <page>
                <content>11111121212</content>
                <count>2</count>
            </page>
            <page>
                <content>131313141414</content>
                <count>2</count>
            </page>
            <page>
                <content>151515161616</content>
                <count>2</count>
            </page>
            <page>
                <content>171717</content>
            </page>
        </subsection>
    </section>
</AllSections>

关于xslt - 如何使用一些空属性进行 xslt Muenchian 分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12862902/

相关文章:

XSLT:获取或匹配 base64 编码数据的哈希值

java - 如何从java代码向XSLT传递参数

xml - 基于属性的唯一 xml 节点

xml - xslt 1.0 中的编程工具

xslt - 从属性值中去除前缀

xslt-1.0 - 使用多个具有相同选择过滤器的应用模板

xslt - 如何在 XPath 中创建引用其他节点的嵌套条件

xml - xslt 在 2 个值之间选择

xslt - 如何在 for-each 循环中的每个元素之间添加分隔符?

xslt - 加载 XSL 代码的外部 block