【问题标题】:How to do xslt Muenchian grouping with some null attributes?如何使用一些空属性进行 xslt Muenchian 分组?
【发布时间】:2012-10-12 15:57:24
【问题描述】:

与标准的 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>

谢谢!

【问题讨论】:

  • 您的预期输出是否正确?为什么 151515 在输入中显示为具有一组“group06”时单独输出。同理,为什么161616,也有一组“group06”,输出131313和141414,都有一组“group05”?

标签: xslt xslt-1.0


【解决方案1】:

对于具有 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>

【讨论】:

  • +1。缺少一个带有&lt;xsl:template match="root"&gt;&lt;AllSections&gt;&lt;xsl:apply-templates/&gt;&lt;/AllSections&gt;&lt;/xsl:template&gt; 的模板,它似乎产生了想要的结果(尽管这与主要的分组问题无关)。
  • 啊,是的。我没有发现根元素的重命名。我已经修改了我的 XSLT 以包含该模板。谢谢!
  • 您好,感谢您提供如此完整的答案。关于扩展这个的快速问题。我需要将带有“内容”的文档作为文件位置而不是字符串。对于我正在使用的非分组元素:
猜你喜欢
  • 2015-07-30
  • 2015-04-10
  • 2014-08-07
  • 2017-11-13
  • 2013-04-21
  • 2013-05-11
  • 2017-11-06
  • 2018-03-28
  • 1970-01-01
相关资源
最近更新 更多