考虑元素属性值,使用xslt重新排列xml

时间:2014-02-14 07:40:41

标签: java xml xslt xsd

我有以下xml:

<Users>
  <User id="2" name="ABC" Division="HR"/> 
  <User id="3" name="xyz" Division="Admin"/> 
  <User id="4" name="LMN" Division="Payroll"/> 
  <User id="5" name="PQR" Division="IT"/> 
</Users>

我想使用XSLT转换它,如下所示:

<Users>
 <User id="5" name="PQR" Division="IT"/>
 <User id="3" name="xyz" Division="Admin"/>
 <User id="2" name="ABC" Division="HR"/> 
 <User id="4" name="LMN" Division="Payroll"/>  
</Users>

我是根据Division属性值来做的,没有具体的规则。 这只是一个样本。 这不是排序,它是一种模板。我可以为用户定义自己的订单并使用xslt进行转换吗?

提前致谢。

1 个答案:

答案 0 :(得分:1)

有许多方法可以在XSLT中重新排列节点,从简单的字母或数字排序到复杂的分组。如果您可以将XSLT 2.0或XSLT 1.0与扩展一起使用,则通常可以在模板或循环和函数中使用<xsl:sort>。如果您受限于XSLT 1.0,您可以在节点集上的模板或循环中进行基本排序,但必须编写更复杂的分组算法(例如:Muenchian方法)。

使用您的简单示例,我想到了一些重新排列节点的方法。使用下面的样式表处理您的示例,您将看到一些示例。

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

    <xsl:output indent="yes" />
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <Results>
            <xsl:apply-templates select="Users" mode="sort-name-alphabetical-asc" />
            <xsl:apply-templates select="Users" mode="sort-division-alphabetical-desc" />
            <xsl:apply-templates select="Users" mode="sort-id-numerical-desc" />
            <xsl:apply-templates select="Users" mode="sort-by-number-of-chars-in-division" />
            <xsl:apply-templates select="Users" mode="sort-by-last-letter-in-name" />
        </Results>   
    </xsl:template>

    <xsl:template match="User">
        <xsl:copy-of select="." />
    </xsl:template>

    <xsl:template match="Users" mode="sort-name-alphabetical-asc">
        <example>Sort by name, alphabetical, ascending</example>
        <xsl:copy>
            <xsl:apply-templates select="User">
                <xsl:sort select="@name" data-type="text" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Users" mode="sort-division-alphabetical-desc">
        <example>Sort by Division, alphabetical, descending</example>
        <xsl:copy>
            <xsl:apply-templates select="User">
                <xsl:sort select="@Division" data-type="text" order="descending" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Users" mode="sort-id-numerical-desc">
        <example>Sort by id, numerical, descending</example>
        <xsl:copy>
            <xsl:apply-templates select="User">
                <xsl:sort select="@id" data-type="number" order="descending" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Users" mode="sort-by-number-of-chars-in-division">
        <example>Sort by number of total chars in Division + name</example>
        <xsl:copy>
            <xsl:apply-templates select="User">
                <xsl:sort select="string-length(@Division) + string-length(@name)" data-type="number" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Users" mode="sort-by-last-letter-in-name">
        <example>Sort by last letter in name</example>
        <xsl:copy>
            <xsl:apply-templates select="User">
                <!-- In XSLT 2.0 you can use node()[ends-with(@name, '')] -->
                <xsl:sort select="substring(@name, string-length(@name)-1, string-length(@name))" data-type="text" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>