XSLT对不同父节点下的子节点进行排序

时间:2019-05-14 12:46:34

标签: xml xslt-2.0

我正在尝试使用xslt对xml进行排序,但问题是我的代码仅对特定节点下的元素进行排序,这是一个示例xml:

<region name="Germany">
    <company name="Mercedes" rank="2" />
    <company name="BMW" rank="3" />
</region>
<region name="Japan">
    <company name="Toyota" rank="1" />
    <company name="Mazda" rank="4" />
</region>

我尝试了以下操作,但没有成功

<xsl:template match="region">
    <Companies>
        <xsl:for-each select="company">
            <xsl:sort select="@rank" />
            <xsl:call-template name="companies">
        </xsl:for-each>
    </Companies>
</xsl:template>

<xsl:template name="companies">
     <Company>
        <xsl:value-of select="@name" />
     </Company>
</xsl:template>

输出应为:

<Companies>
    <Company>Toyota</Company>
    <Company>Mercedes</Company>
    <Company>BMW</Company>
    <Company>Mazda</Company>
</Companies>

2 个答案:

答案 0 :(得分:1)

在输出中,您似乎想按等级而不是名称进行排序。

关于随节点进行的排序,因为您的模板正在每个区域运行,所以排序是针对一个区域内的公司节点。 您可以为区域的父级运行模板,然后遍历元素并按名称排序。 这是具有匹配输出的模板。

<xsl:template match="*[region]">
    <Companies>
        <xsl:for-each select="region/company">
            <xsl:sort select="@rank" />
            <xsl:call-template name="companies" />
        </xsl:for-each>
    </Companies>
</xsl:template>

<xsl:template name="companies">
     <Company>
        <xsl:value-of select="@name" />
     </Company>
</xsl:template> 

答案 1 :(得分:1)

对于这些region元素,您没有显示任何容器元素,但是假设您将它们包含在一个公共容器中,请编写一个与该容器匹配的模板(例如,在下面的示例代码中名为root),然后我只是建议将模板应用于包含company属性的xsl:sort的{​​{1}}孙子。

然后添加一个模板,该模板从基于属性的rank输入元素转换为基于值的元素,您已完成:

company

https://xsltfiddle.liberty-development.net/94rmq6B

如果要以一种排序的方式一起处理所有<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" version="3.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="root"> <Companies> <xsl:apply-templates select="region/company"> <xsl:sort select="xs:integer(@rank)"/> </xsl:apply-templates> </Companies> </xsl:template> <xsl:template match="company"> <xsl:copy> <xsl:value-of select="@name"/> </xsl:copy> </xsl:template> </xsl:stylesheet> ,似乎没有任何意义。