如何使用 XSLT 按 ID 值对 XML 个节点进行排序?

How to sort XML nodes by ID values using XSLT?

我有一个包含很多行节点的大型 xml 文件。我想按每一行的 id 值对其进行排序。

所以这将是一个示例输入:

<database>
  <table>
    <row>
      <id>10</id>
      <foo>bar</foo>
    </row>
    <row>
      <id>5</id>
      <foo>poit</foo>
    </row>
    <row>
      <id>1</id>
      <foo>narf</foo>
    </row>
  </table>
</database>

这是预期的输出:

<database>
  <table>
    <row>
      <id>1</id>
      <foo>narf</foo>
    </row>
    <row>
      <id>5</id>
      <foo>poit</foo>
    </row>
    <row>
      <id>10</id>
      <foo>bar</foo>
    </row>
  </table>
</database>

我怎样才能做到这一点?我有 xmlstarlet 供我使用。它有一个 transform 并且看起来我可以在 xsl 文件中提供一个 xslt 样式表。

我以前没有使用过 xslt,不确定如何继续。

我发现 some related sorting questions 提供了一些 XSLT 示例,但我无法在我的用例中使用它们。

我目前的sort.xslt(注意:我不知道我在做什么)看起来像:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="@*">
    <xsl:sort select="row()"/>
   </xsl:apply-templates>
   <xsl:apply-templates select="node()">
    <xsl:sort select="id()"/>
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

然而它失败了:

$ xmlstarlet tr sort.xsl example.xml 
Invalid number of arguments
xmlXPathCompiledEval: evaluation failed
Invalid number of arguments
xmlXPathCompiledEval: evaluation failed
Invalid number of arguments
xmlXPathCompiledEval: evaluation failed
<database>
  <table/>
</database>

我对 xmlstarlet 一无所知,但我可以说您的 XSLT 应该看起来像这样...

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

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

    <xsl:template match="table">
        <xsl:copy>
            <xsl:apply-templates select="row">
                <xsl:sort select="id" data-type="number" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

请注意,在 XSLT 中的元素名称后不需要 ()

http://xsltransform.net/pNmBy1b

查看实际效果

(我还注意到标签 xmlstarlet 只有 20 个关注者。您可能想尝试一些其他工具。请参阅 https://whosebug.com/tags/xslt/info 以获得帮助。也许是 xsltproc?)