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

3
我有一个包含许多行节点的大型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。它具有转换功能,显然我可以在xsl文件中提供xslt样式表。
我以前没有使用过xslt,不确定该怎么做。
我找到了一些相关的排序问题,提供了一些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>
1个回答

2
我不了解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://stackoverflow.com/tags/xslt/info获取一些帮助。也许是xsltproc?)

xmlstarlet 运行良好:xmlstarlet tr sort.xsl example.xml | xmlstarlet fo - ;) 谢谢,这是我需要的启动。 - k0pernikus
附注:xmlstarlet希望这是一个更大文件的1.0版本。尽管如此,它似乎仍在工作。 - k0pernikus
我的样式表实际上是“1.0”版本的,我只是忘记更改版本号了。如果将带有“2.0”版本的样式表提供给XSLT 1.0进程,则它将以“向前兼容”模式运行,并且将忽略任何它不认识的xsl指令。 - Tim C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接