Muenchian组在XSLT 1.0中选择了一些元素

时间:2016-12-21 13:02:06

标签: xml xslt xslt-1.0 grouping xslt-grouping

考虑这个带有标题,类别和联盟的足球比赛的XML文档。

<?xml version='1.0'?>
<games>
    <game>
        <title>Manchester City - Arsenal</title>
        <category>Live</category>
        <league>Premier League</league>
    </game>
    <game>
        <title>Barcelona - Real Madrid</title>
        <category>Live</category>
        <league>Primera Division</league>
    </game>
    <game>
        <title>Arsenal - Hull City</title>
        <category>Recap</category>
        <league>Premier League</league>
    </game>
    <game>
        <title>Everton - Liverpool</title>
        <category>Live</category>
        <league>Premier League</league>
    </game>
    <game>
        <title>Zaragoza - Deportivo</title>
        <category>Short Recap</category>
        <league>Primera Division</league>
    </game>
</games>

我正在尝试按类别对这些游戏进行分组,但我只想保留<league>元素为'英超联赛'的记录。该类别还应具有count属性,该属性列出了相应记录的数量。

以下XSL文件将起作用,但缺点是它还会列出未找到“英超联赛”游戏的类别。理想情况下,根本不应该有那些类别标签。

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

 <xsl:key name="prod-cat" match="game" use="category"/>

    <xsl:template match="/">
        <root>
            <xsl:for-each select="games/game[count(. | key('prod-cat', category)[1]) = 1]">

                <category>

                <xsl:variable name="cat">
                    <xsl:value-of select="category"/>
                </xsl:variable>

                <xsl:variable name="count">
                    <xsl:value-of select="count(//game[category = $cat][league = 'Premier League'])"/>
                </xsl:variable>

                <xsl:attribute name="name">
                    <xsl:value-of select="category"/>
                </xsl:attribute>

                <xsl:attribute name="count">
                    <xsl:value-of select="$count"/>
                </xsl:attribute>

                    <xsl:for-each select="key('prod-cat', $cat)[league = 'Premier League']">
                        <game>
                            <title>
                                <xsl:value-of select="title"/>
                            </title>
                            <cat>
                                <xsl:value-of select="category"/>
                            </cat>
                            <series>
                                <xsl:value-of select="league"/>
                            </series>
                        </game>
                    </xsl:for-each>
                </category>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:transform>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <category name="Live" count="2">
      <game>
         <title>Manchester City - Arsenal</title>
         <cat>Live</cat>
         <series>Premier League</series>
      </game>
      <game>
         <title>Everton - Liverpool</title>
         <cat>Live</cat>
         <series>Premier League</series>
      </game>
   </category>
   <category name="Recap" count="1">
      <game>
         <title>Arsenal - Hull City</title>
         <cat>Recap</cat>
         <series>Premier League</series>
      </game>
   </category>
   <category name="Short Recap" count="0"/> <!--This one needs to go-->
</root>

2 个答案:

答案 0 :(得分:1)

我会将条件纳入关键定义:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    <xsl:key name="prod-cat" match="game[league = 'Premier League']" use="category"/>
    <xsl:template match="/">
        <root>
            <xsl:for-each select="games/game[league = 'Premier League'][count(. | key('prod-cat', category)[1]) = 1]">
                <category name="{category}" count="{count(key('prod-cat', category))}">
                    <xsl:for-each select="key('prod-cat', category)">
                        <game>
                            <title>
                                <xsl:value-of select="title"/>
                            </title>
                            <cat>
                                <xsl:value-of select="category"/>
                            </cat>
                            <series>
                                <xsl:value-of select="league"/>
                            </series>
                        </game>
                    </xsl:for-each>
                </category>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:transform>

http://xsltransform.net/ejivdHq/1在线。

答案 1 :(得分:0)

这是一个优化和更正的版本。您只能将所需元素分组,过滤掉其余元素。
编辑:感谢Martin Honnen。我添加了一个xsl:if来取消输出中不相关的元素。

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    <xsl:key name="prod-cat" match="game" use="category"/>
    <xsl:template match="/">
        <root>
            <xsl:for-each select="games/game[count(. | key('prod-cat', category)[1]) = 1]">
                <xsl:if test="key('prod-cat', category)[league = 'Premier League']">
                    <category name="{category}" count="{count(key('prod-cat', category)[league = 'Premier League'])}">
                        <xsl:for-each select="key('prod-cat', category)[league = 'Premier League']">
                            <game>
                                <title>
                                    <xsl:value-of select="title"/>
                                </title>
                                <cat>
                                    <xsl:value-of select="category"/>
                                </cat>
                                <series>
                                    <xsl:value-of select="league"/>
                                </series>
                            </game>
                        </xsl:for-each>
                    </category>
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:transform>