XSLT子分组

时间:2018-05-22 20:27:37

标签: xslt xslt-1.0

我需要帮助XSLT 1.0中的子分组。我有以下输入XML

<Items>
<Item>
    <Major>Major 1</Major>
    <Detail>
        <Minor>Minor 1</Minor>
        <Info>
            <Name>Name 1</Name>
            <DayRate>12.00</DayRate>
            <WeekRate>13.00</WeekRate>
            <MonthRate>14.00</MonthRate>
        </Info>
    </Detail>
</Item>
<Item>
    <Major>Major 2</Major>
    <Detail>
        <Minor>Minor 2</Minor>
        <Info>
            <Name>Name 1</Name>
            <DayRate>15.00</DayRate>
            <WeekRate>16.00</WeekRate>
            <MonthRate>17.00</MonthRate>
        </Info>
        <Info>
            <Name>Name 2</Name>
            <DayRate>25.00</DayRate>
            <WeekRate>26.00<WeekRate>
            <MonthRate>27.00</MonthRate>
        </Info>
    </Detail>
</Item>

我想要的输出如下

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0"/>

<xsl:key name="minor-cat" match="/Items/Item" use="MINOR/text()"/>

<xsl:template match="/Items">
    <Items>
        <xsl:for-each select="key('minor-cat', Item/MINOR/text())">
            <Item>
                <Major>
                    <xsl:value-of select="MAJOR/text()"/>
                </Major>
                <Detail>
                    <Minor>
                        <xsl:value-of select="MINOR/text()"/>
                    </Minor>
                    <Info>
                        <Name>
                            <xsl:value-of select="NAME/text()"/>
                        </Name>
                        <DayRate>
                            <xsl:value-of select="DAYRATE/text()"/>
                        </DayRate>
                        <WeekRate>
                            <xsl:value-of select="WEEKRATE/text()"/>
                        </WeekRate>
                        <MonthRate>
                            <xsl:value-of select="MONTHRATE/text()"/>
                        </MonthRate>
                    </Info>
                </Detail>
            </Item>
        </xsl:for-each>
    </Items>
</xsl:template>

基本上,我想首先将Major分组,然后按Minor分组。寻找XSLT 1.0解决方案。

感谢任何帮助。

谢谢。

我尝试使用以下XSLT,但Minor分组无效。

A

2 个答案:

答案 0 :(得分:0)

在XSLT-1.0中,您必须使用Muenchian Grouping复合键来实现此目的。

您只需对XSLT进行四处更改:

  • 一个key创建复合键
  • 一个到for-each实现 Muenchian分组
  • 复合键
  • 创建对十进制格式敏感的number类型排序键
  • 通过上面创建的数字将此排序键添加到sort输出

这是完整的XSLT-1.0:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0"/>

<!-- Modified to use a composite key -->
<xsl:key name="minor-cat" match="/Items/Item" use="concat(MAJOR/text(),'.',MINOR/text())"/>          

<xsl:template match="/Items">
    <Items>
        <!-- Modified to use Muenchian Grouping -->
        <xsl:for-each select="Item[generate-id() = generate-id(key('minor-cat', concat(MAJOR/text(),'.',MINOR/text()))[1])]">   
            <!-- Added to sort by key -->
            <xsl:sort select="number(concat(substring-after(MAJOR/text(),' '),'.',substring-after(MINOR/text(),' ')))" data-type="number" /> 
            <!-- Process all elements with the same Major/Minor value -->
            <xsl:for-each select="key('minor-cat', concat(MAJOR/text(),'.',MINOR/text()))">
                <Item>
                    <Major>
                        <xsl:value-of select="MAJOR/text()"/>
                    </Major>
                    <Detail>
                        <Minor>
                            <xsl:value-of select="MINOR/text()"/>
                        </Minor>
                        <Info>
                            <Name>
                                <xsl:value-of select="NAME/text()"/>
                            </Name>
                            <DayRate>
                                <xsl:value-of select="DAYRATE/text()"/>
                            </DayRate>
                            <WeekRate>
                                <xsl:value-of select="WEEKRATE/text()"/>
                            </WeekRate>
                            <MonthRate>
                                <xsl:value-of select="MONTHRATE/text()"/>
                            </MonthRate>
                        </Info>
                    </Detail>
                </Item>
            </xsl:for-each>
        </xsl:for-each>
    </Items>
</xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

<xsl:template match="Items">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Item">
        <xsl:copy>
            <xsl:apply-templates select="MAJOR"/>
            <xsl:apply-templates select="MINOR"/>
            <xsl:apply-templates select="NAME"/>
            <xsl:apply-templates select="DAYRATE|WEEKRATE|MONTHRATE"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="MAJOR">
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="MINOR">
        <DETAIL>
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
            <xsl:apply-templates select=" following-sibling::NAME"/>
        </DETAIL>
    </xsl:template>
    <xsl:template match="NAME">
        <INFO>
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
            <xsl:apply-templates select="preceding-sibling::DAYRATE|preceding-sibling::WEEKRATE|preceding-sibling::MONTHRATE"/>
        </INFO>
    </xsl:template>
    <xsl:template match="DAYRATE">
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="WEEKRATE">
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="MONTHRATE">
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>
Check it if it is useful for you