3

如何使用 XSLT 控制属性排序?

我有一个输入 XML 文档:

输入 XML

<?xml version="1.0" encoding="UTF-8"?>
<allNames id="ID_0" b:type="a:UnstructuredName">
    <typeName>KnownBy</typeName>
    <startDate>2001-01-01-05:00</startDate>
    <fullName>ABCD 004 COMPANY INC</fullName>
</allNames>

我需要应用 XSLT 将其转换为

输出 XML

<?xml version="1.0" encoding="UTF-8"?>
<allNames  b:type="a:UnstructuredName"  id="ID_0">
    <typeName>KnownBy</typeName>
    <startDate>2001-01-01-05:00</startDate>
    <fullName>ABCD 004 COMPANY INC</fullName>
</allNames>

唯一的变化是元素中的属性排序变化。allNames我查阅了另一篇文章并编写了用于排序属性的 XSLT,但我不知道如何让整个事情正常工作。

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" indent="yes"/>
    <xsl:variable name="attributes" select="document('mytest.xml')//attribute"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*">
        <xsl:variable name="self" select="."/>
        <xsl:for-each select="$attributes">
            <xsl:apply-templates select="$self/@*[name()=current()]"/>
        </xsl:for-each>   
     </xsl:template>
</xsl:stylesheet>

mytest.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <attributes>
        <attribute>b:type</attribute>
        <attribute>id</attribute>
    </attributes>
4

2 回答 2

8

根据XML 建议,属性顺序无关紧要

请注意,开始标签或空元素标签中属性规范的顺序并不重要。

因此,XSLT 无法控制输出的属性排序。

W3C 推荐中的属性排序

一般来说,XML 建议都会认为属性排序无关紧要,但如果您的应用程序需要属性排序,请参阅XML 规范化建议规范 XML 建议中的属性处理部分。但是,您必须在标准 XSLT 之外执行此操作。

属性排序实现黑客

如果您认识到对 XML 属性进行排序本质上是有缺陷的,与互操作性背道而驰,并且完全超出了 XML 建议和使用 XML 的既定实践,但您仍然必须控制属性排序,这里有一些方法实施这样的控制...

正如 Michael Kay 在对这个问题的另一个回答中提到的,Saxon 9.5(PE 或更高版本)有一个 XSLT 扩展,可以控制序列化程序的属性顺序。详情请参阅saxon:attribute-order

您可以对标准 XSLT 生成的 XML 进行后处理。在 XML 库级别下操作,您当然可以通过字符或字符串级别处理获得对属性排序的完全词法控制。

您可以依赖 XML 库提供的排序的实现细节。例如,一些库会根据属性名称按字母顺序写出属性,或者会保留提供给它们的属性顺序。显然,依赖实现细节本质上是不可靠的。也就是说,例如,XMLStreamWriter.writeAttribute未来的实现可能会继续遵守赋予它们的属性顺序。

对所有 XML 属性排序问题的真正答案的最后一次重申是在结束之前按顺序排列......

将 XML 属性视为具有顺序与XML 建议相反,应该避免。

于 2013-11-01T00:02:05.980 回答
4

Saxon 9.5(PE 或更高版本)提供了一个序列化选项saxon:attribute-order,允许您控制序列化程序生成的属性顺序。尽管属性顺序对任何正常的接收应用程序都没有任何影响,但一致的顺序可以提高 XML 的可读性,并且由于可读性是 XML 的目标之一,我认为这是一个合理的添加特性。

于 2013-11-01T09:38:13.710 回答