XSLT - 传递属性以创建父元素,然后对筛选结果进行排序

时间:2017-09-23 20:21:10

标签: xslt

我在一段时间后回到学习XSLT并发现自己在推送方法上苦苦挣扎。

来自以下(简化)文件:

<Index>
    <Person id="Je1" age="30" nationality="Fra">Jean</Person>
    <Person id="Ma1" age="30" nationality="Eng">Mary</Person>
    <Person id="Je2" age="40" nationality="Fra">Jean</Person>
    <Person id="Lu1" age="20" nationality="Ita">Luigi</Person>
    <Person id="He1" age="50" nationality="Gre">Hector</Person>
    <Person id="Pe1" age="45" nationality="Gre">Penelope</Person>
</Index>

我想: 1.使用属性&#34;国籍&#34;的不同值创建排序元素, 2.将项目传递给相应的元素 3.根据另一个原始属性对它们进行排序,例如&#34;年龄&#34;

<OrderedIndex>
    <Country key="Eng">
        <Person id="Ma1" age="30" nationality="E">Mary</Person>
    </Country>
    <Country key="Fra">
        <Person id="Je1" age="30" nationality="F">Jean</Person>
        <Person id="Je2" age="40" nationality="F">Jean</Person>
    </Country>
    <Country key="Gre">
        <Person id="Pe1" age="45" nationality="Gre">Penelope</Person>
        <Person id="He1" age="50" nationality="Gre">Hector</Person>
    </Country>
    <Country key="Ita">
        <Person id="Lu1" age="20" nationality="Ita">Luigi</Person>
    </Country>
</OrderedIndex>

我正在管理第一步:

<xsl:variable name="cou" select="distinct-values(//@nationality)"/>
<xsl:template match="*">
    <xsl:text>&#xa;</xsl:text>
    <List>
    <xsl:for-each select="$cou">
        <xsl:sort/>
        <xsl:text>&#xa;</xsl:text>
        <xsl:element name="country">
            <xsl:attribute name="country">
                <xsl:copy-of select="."/>
            </xsl:attribute>
        </xsl:element>
    </xsl:for-each>
    <xsl:text>&#xa;</xsl:text>
    </List>
</xsl:template>

- 但在此之后我无法使用<apply-templates><for-each>。显然,在选择过程中我不明白。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您的distinct-values正在选择@n属性,但我认为您的意思是选择@nationality属性

<xsl:variable name="cou" select="distinct-values(//@nationality)"/>

但是,distinct-values可能不是此处使用的最佳选择,因为它返回一系列原子值,因此您将不再处于原始XML文档的上下文中。 xsl:for-each-group可能是更好的匹配

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/*">
        <OrderedIndex>
            <xsl:for-each-group select="Person" group-by="@nationality">
                <xsl:sort select="@nationality"/>
                <Country key="{current-grouping-key()}">
                    <xsl:apply-templates select="current-group()">
                        <xsl:sort select="@age" />
                    </xsl:apply-templates>
                </Country>
            </xsl:for-each-group>
        </OrderedIndex>
    </xsl:template>

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

注意:

  • 输出XML时确实没有必要尝试输出换行符(除非你有一些特殊要求)。只需使用indent

  • 上的xsl:output选项即可
  • 身份模板用于复制Person元素

  • 请注意在key元素上创建country属性时使用Attribute Value Templates

另请注意,如果您确实想使用distinct-values,可以这样做......

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:variable name="cou" select="distinct-values(//@nationality)"/>
    <xsl:variable name="root" select="/"/>

    <xsl:key name="people" match="Person" use="@nationality" />

    <xsl:template match="/*">
        <List>
        <xsl:for-each select="$cou">
            <xsl:sort select="." />
            <country key="{.}">
                <xsl:apply-templates select="apply-templates select="">
                    <xsl:sort select="@age" />
                </xsl:apply-templates>
            </country>
        </xsl:for-each>
        </List>
    </xsl:template>

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