简体   繁体   English

使用XSLT 1.0的嵌套分组

[英]Nested Grouping using XSLT 1.0

I'm having some difficulties with nested grouping in XSLT 1.0. 我在XSLT 1.0中的嵌套分组方面遇到一些困难。 The problem is a few documents have multiple products in their metadata. 问题是一些文档的元数据中有多个产品。 First, I need to group the results by the products. 首先,我需要将结果按产品分组。 Finally, grouping by types is expected as well. 最后,也期望按类型分组。 Actually, I gained the goals using for-each-group instruction from XSLT 2.0. 实际上,我使用XSLT 2.0中的for-each-group指令实现了目标。 But the thing is, I`m not able to change the version of XSLT in my project. 但问题是,我无法在项目中更改XSLT的版本。

I would greatly appreciate it if someone could help me to implement this requirements in XSLT 1.0. 如果有人可以帮助我在XSLT 1.0中实现此要求,我将不胜感激。 I`m wondering if it is possible to use the Muenchian method there and what the named keys are look like. 我想知道是否可以在此处使用Muenchian方法以及命名键的外观。

Here is an example of input xml: 这是输入xml的示例:

<result>
    <document>
        <metadata>
            <title>Academic Program Directors</title>
            <type>typeA</type>
            <product>Product1</product>
            <product>Product2</product>
            <product>Product3</product>
        </metadata>
    </document>
    <document>
        <metadata>
            <title>Administrative Directors</title>
            <type>typeA</type>
            <product>Product2</product>
        </metadata>
    </document>
    <document>
        <metadata>
            <title>Program Managers</title>
            <type>typeB</type>
            <product>Product1</product>
            <product>Product3</product>
        </metadata>
    </document>
</result>

The expect output would be the following: 预期的输出如下:

Product1
    typeA
        Academic Program Directors
    typeB
        Program Managers

Product2
    typeA
        Academic Program Directors
        Administrative Directors

Product3
    typeA
        Academic Program Directors
    typeB
        Program Managers

Here's the XSLT 2.0 solution 这是XSLT 2.0解决方案

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/result">
        <xsl:for-each-group select="document/metadata" group-by="product">
            <xsl:sort select="current-grouping-key()"/>
            <p style="font-weight: bold;">
                <xsl:value-of select="current-grouping-key()"/>
            </p>

            <xsl:for-each-group select="current-group()" group-by="type">
                <xsl:sort select="current-grouping-key()"/>
                <p style="padding-left: 2em;">
                    <xsl:value-of select="current-grouping-key()"/>
                </p>

                <xsl:for-each select="current-group()">
                    <p style="padding-left: 4em;">
                        <xsl:value-of select="title"/>
                    </p>
                </xsl:for-each>
            </xsl:for-each-group>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

A lot of XSLT 1 processors implement set:distinct ( http://exslt.org/set/functions/distinct/index.html ) so with that you can use the approach in http://xsltransform.net/bEzjRKX which does 许多XSLT 1处理器都实现了set:distincthttp://exslt.org/set/functions/distinct/index.html ),因此您可以使用http://xsltransform.net/bEzjRKX中的方法

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:set="http://exslt.org/sets" exclude-result-prefixes="set">

    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/result">
        <xsl:variable name="metas" select="document/metadata"/>
        <xsl:for-each select="set:distinct($metas/product)">
            <xsl:sort select="."/>
            <p style="font-weight: bold;">
                <xsl:value-of select="."/>
            </p>
            <xsl:variable name="current-group" select="$metas[product = current()]"/>
            <xsl:variable name="types" select="set:distinct($current-group/type)"/>
            <xsl:for-each select="$types">
                <xsl:sort select="."/>
                <p style="padding-left: 2em;">
                    <xsl:value-of select="."/>
                </p>

                <xsl:for-each select="$current-group[type = current()]">
                    <p style="padding-left: 4em;">
                        <xsl:value-of select="title"/>
                    </p>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

</xsl:transform>

Using keys and Muenchian grouping I think the problem can be solved with 我认为使用键和Muenchian分组可以解决此问题

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:set="http://exslt.org/sets" exclude-result-prefixes="set">

    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/result">
        <xsl:variable name="metas" select="document/metadata"/>
        <xsl:for-each select="set:distinct($metas/product)">
            <xsl:sort select="."/>
            <p style="font-weight: bold;">
                <xsl:value-of select="."/>
            </p>
            <xsl:variable name="current-group" select="$metas[product = current()]"/>
            <xsl:variable name="types" select="set:distinct($current-group/type)"/>
            <xsl:for-each select="$types">
                <xsl:sort select="."/>
                <p style="padding-left: 2em;">
                    <xsl:value-of select="."/>
                </p>

                <xsl:for-each select="$current-group[type = current()]">
                    <p style="padding-left: 4em;">
                        <xsl:value-of select="title"/>
                    </p>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

</xsl:transform>

Online at http://xsltransform.net/ehVYZNZ 在线http://xsltransform.net/ehVYZNZ

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM