如何使用 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?)
我有一个包含很多行节点的大型 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?)