XSLT按标记名称和属性值排序

ree*_*eef 4 sorting xslt

我是XSLT的菜鸟,所以请原谅我的无知...我试图按属性值和标签名称对一个简单的XML文件进行排序,但我很难访问该属性的值.这是一个完整的例子:

<a>
    <b attribute="e"></b>
    <b attribute="b"></b>
    <d attribute="a"></d>
    <c></c>
</a>
Run Code Online (Sandbox Code Playgroud)

预期的结果是:

<a>
    <b attribute="b"></b>
    <b attribute="e"></b>
    <c></c>
    <d attribute="a"></d>
</a>
Run Code Online (Sandbox Code Playgroud)

我试图解决这个问题:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" />
    <xsl:strip-space elements="*" />

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

            <xsl:apply-templates select="node()">
                <xsl:sort select="name()"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

这显然根本不起作用......

在上面的例子中,我想按照它们的属性值对b标签进行排序,但是你可以看到d标签没有按属性值排序,因为它是另一个标签名称......

我想知道使用XSLT是否可行......你有什么想法吗?

提前致谢.

UPDATE ----------------------

我尝试了似乎工作正常并且看起来非常简单的andyb解决方案,但我对此解决方案有另一个问题.

假设我有这个XML:

<a>
    <b attribute="e" optionalAttr="fg"></b>
    <b attribute="b"></b>
    <d attribute="a"></d>
    <c></c>
</a>
Run Code Online (Sandbox Code Playgroud)

我为b标签添加了一个可选参数.应用andyb解决方案将忽略可选参数,因为它在模板中不匹配.结果如下:

<a>
    <b attribute="b"></b>
    <b attribute="e"></b>
    <c></c>
    <d attribute="a"></d>
</a>
Run Code Online (Sandbox Code Playgroud)

而不是以下是我所期望的:

<a>
    <b attribute="b"></b>
    <b attribute="e" optionalAttr="fg"></b>
    <c></c>
    <d attribute="a"></d>
</a>
Run Code Online (Sandbox Code Playgroud)

你有什么主意吗?提前致谢.

and*_*dyb 7

您可以使用多个xsl:sort指令,例如:

<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*">
      <xsl:sort select="name()" />
      <xsl:sort select="@*" />
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

由于默认数据类型为"text",默认顺序为"ascending",因此提供了所需的输出.

编辑

这很奇怪,因为对于以下XML:

<a>
    <b attribute="e" optionalAttr="fg"></b>
    <b attribute="b"></b>
    <d attribute="a"></d>
    <c></c>
</a>
Run Code Online (Sandbox Code Playgroud)

和上面的XSL,我得到这个结果:

<a>
    <b attribute="b"></b>
    <b attribute="e" optionalAttr="fg"></b>
    <c></c>
    <d attribute="a"></d>
</a>
Run Code Online (Sandbox Code Playgroud)

这包括所需的可选属性,但顺序与编辑的问题中的XML不同(<c></c>位于不同的位置).


Dim*_*hev 7

此XSLT 2.0转换按元素名称和多个属性名称和值执行排序:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:sort select="name()" />
                <xsl:sort select="my:attributeScore(.)" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:function name="my:attributeScore" as="xs:string">
      <xsl:param name="pThis" as="node()"/>

      <xsl:variable name="vScore">
          <xsl:for-each select="$pThis/@*">
           <xsl:sort select="name()"/>

           <xsl:value-of select="concat(name(),'+',.)"/>
          </xsl:for-each>
          <xsl:text>|</xsl:text>
      </xsl:variable>

      <xsl:sequence select="string-join($vScore, '')"/>
    </xsl:function>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于此XML文档(提供的文档,但添加了多个属性)时:

<a>
    <b attribute="e" x="y"></b>
    <b attribute="e" x="x"></b>
    <b attribute="b"></b>
    <d attribute="a"></d>
    <c></c>
</a>
Run Code Online (Sandbox Code Playgroud)

生成正确排序的结果:

<a>
   <b attribute="b"/>
   <b attribute="e" x="x"/>
   <b attribute="e" x="y"/>
   <c/>
   <d attribute="a"/>
</a>
Run Code Online (Sandbox Code Playgroud)