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

时间:2017-06-30 13:08:59

标签: xml sorting xslt xmlstarlet

我有一个包含大量行节点的大型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>

1 个答案:

答案 0 :(得分: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?)