xml - 按属性值排序时复制所有元素
问题描述
我有这个 XML
<root xmlns:temp ="temp.com">
<testNode name="a">
<sample/>
</testNode>
<testNode name="b">
<sample/>
</testNode>
<testNode name="c">
<sample/>
</testNode>
<testNode name="d">
<sample/>
</testNode>
<testNode name="b">
<sample/>
</testNode>
</root>
我想编写一个转换来复制所有内容,同时按 name 属性的值对 testNodes 进行排序。
预期的输出是:
<root xmlns:temp ="temp.com">
<testNode name="a">
<sample/>
</testNode>
<testNode name="b">
<sample/>
</testNode>
<testNode name="b">
<sample/>
</testNode>
<testNode name="c">
<sample/>
</testNode>
<testNode name="d">
<sample/>
</testNode>
</root>
命名空间可能让我失望,但我似乎无法对结果进行排序。
到目前为止我尝试过的 XSLT 是:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:temp="temp.com"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()">
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template name="temp:root">
<xsl:copy>
<xsl:apply-templates select="temp:testNode">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
解决方案
更新
鉴于您问题中的修订信息,您当前的 XSLT 和源 XML 存在一些问题:
1)<xsl:template name="temp:root">
应该是<xsl:template match="temp:root">
。即您需要使用match
来定位要转换的元素,而不是name
允许您调用模板。
2) 您的源 XML 声明了temp
前缀,但不使用它。你应该使用:
<root xmlns="temp.com">
<testNode name="a">
<sample/>
...创建一个默认名称空间(前缀与 XSLT 的前缀不同并不重要;它们只是真实名称空间的别名)。这意味着任何没有命名空间的元素都使用命名temp.com
空间。
或者
<temp:root xmlns:temp="temp.com">
<temp:testNode name="a">
<temp:sample/>
因此,您可以使用前缀为temp.com
命名空间中定义的元素添加temp
前缀。
这是一个固定的 XSLT Fiddle:http: //xsltfiddle.liberty-development.net/3NzcBto
注意:如果您希望您的 XSLT 与命名空间无关,您也可以使用该local-name()
函数。
<xsl:template match="*[local-name()='root']">
<xsl:copy>
<xsl:apply-templates select="*[local-name()='testNode']">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
通常这不是一个好主意,因为调用函数会产生性能开销,并且您会失去命名空间的好处;但它在各种情况下都有帮助;特别是在开发过程中,如果您不确定某个问题是否与命名空间相关的问题有关。
原始答案
使用xsl:sort
此处记录的元素:https ://www.w3schools.com/xml/xsl_sort.asp
示例:XSLT 小提琴
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8" /> <!-- keeping utf 8 rather than 16 as this will be big -->
<xsl:strip-space elements="*"/>
<!-- By default, copy everything as is -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- but sort the child elements of our root element by their name attribute -->
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="@* | node()">
<xsl:sort select="./@name" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
推荐阅读
- php - 在 PHP 中使用可变数量的参数动态调用构造函数
- javascript - 单击链接时,选择 html 表的某些行并将所选行的一列的值发送到另一个 php 页面
- java - 使用美国运通/节点的 GraphQL 查询列表
- javascript - 使用 JavaScript 为 MS Outlook 生成长电子邮件正文
- r - R中两个矩阵(data.frames)列的余弦相似度
- mysql - 匹配 2 个具有特定条件的 SQL 表
- java - 托管到服务器时,登录在 Spring Boot(使用 Spring Security)中不起作用
- aws-lambda - “缺少身份验证令牌”错误,身份验证类型设置为 NONE
- c# - 使用 Vuforia 时,如何在删除目标图像时阻止我的组件显示?
- android - 通过 Util 类绑定数据时模型类中的绑定错误