排序 XML 模式而不重新排序命名元素的子元素
Sort XML Schema without reordering children of named element
我们从模型生成 XML 模式,但我们发现这会导致 XML 模式随时间重新排序。这不是我们可以轻易控制的事情,因此我们打算对生成的 XML 模式应用 XSLT 转换,以便为它们提供更稳定的顺序。
为实现这一点,我们考虑先根据元素名称对元素重新排序,然后是属性(name
理想情况下优先于其他属性)。
即按
排序
<element>
(元素名称)
<element name="xyz">
(属性'name')
<element *="*">
(所有其他属性)
然而,有一组元素我们无法对其子元素重新排序,即 <xs:sequence>
,因为它们具有严格的顺序。
下面是一个不能更改顺序的示例定义。
<xs:complexType name="OBJECT.OtherSystemClaimsXref">
<xs:sequence>
<xs:group ref="FIELDS.OtherSystemClaimsXref"/>
<xs:group ref="FIELDS.ExternallyMaintained"/>
<xs:group ref="FIELDS.DtoSupplier"/>
<xs:group ref="FIELDS.BusinessObject"/>
<xs:group ref="FIELDS.OtherSystemXrefAbstract"/>
</xs:sequence>
<xs:attribute name="externalSystemReference" type="TYPE.OpenTwinsExternalReference" use="required"/>
<xs:attribute name="dataChangedEnum" type="ENUM.DataChangedEnum" use="optional"/>
<xs:attribute name="importable" type="xs:boolean" use="optional"/>
</xs:complexType>
我想出了下面的 XSLT 作为起点。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="no" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()">
<xsl:sort select="name()" />
<xsl:sort select="@*" order="ascending" data-type="text" />
<xsl:sort select="." />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:strip-space elements="*" />
</xsl:stylesheet>
我试图通过阻止 <xs:sequence>
的排序来改变行为,但这没有用。
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*[not(local-name()='sequence')]">
<xsl:sort select="name()" />
<xsl:sort select="@*" order="ascending" data-type="text" />
<xsl:sort select="." />
</xsl:apply-templates>
<xsl:apply-templates select="*[local-name()='sequence']"/>
</xsl:copy>
除了 <xs:sequence>
的直系子代之外,我如何将这些规则应用于所有对象?
非常感谢。
如果您不希望 xsl:sequence
的子项被排序,您应该为此添加一个优先于通用模板的特定模板。
<xsl:template match="xs:sequence">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
这将要求您在样式表中声明 xs
命名空间前缀。
试试这个 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes" omit-xml-declaration="no" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()">
<xsl:sort select="name()" />
<xsl:sort select="@*" order="ascending" data-type="text" />
<xsl:sort select="." />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="xs:sequence">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我们从模型生成 XML 模式,但我们发现这会导致 XML 模式随时间重新排序。这不是我们可以轻易控制的事情,因此我们打算对生成的 XML 模式应用 XSLT 转换,以便为它们提供更稳定的顺序。
为实现这一点,我们考虑先根据元素名称对元素重新排序,然后是属性(name
理想情况下优先于其他属性)。
即按
排序<element>
(元素名称)<element name="xyz">
(属性'name')<element *="*">
(所有其他属性)
然而,有一组元素我们无法对其子元素重新排序,即 <xs:sequence>
,因为它们具有严格的顺序。
下面是一个不能更改顺序的示例定义。
<xs:complexType name="OBJECT.OtherSystemClaimsXref">
<xs:sequence>
<xs:group ref="FIELDS.OtherSystemClaimsXref"/>
<xs:group ref="FIELDS.ExternallyMaintained"/>
<xs:group ref="FIELDS.DtoSupplier"/>
<xs:group ref="FIELDS.BusinessObject"/>
<xs:group ref="FIELDS.OtherSystemXrefAbstract"/>
</xs:sequence>
<xs:attribute name="externalSystemReference" type="TYPE.OpenTwinsExternalReference" use="required"/>
<xs:attribute name="dataChangedEnum" type="ENUM.DataChangedEnum" use="optional"/>
<xs:attribute name="importable" type="xs:boolean" use="optional"/>
</xs:complexType>
我想出了下面的 XSLT 作为起点。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="no" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()">
<xsl:sort select="name()" />
<xsl:sort select="@*" order="ascending" data-type="text" />
<xsl:sort select="." />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:strip-space elements="*" />
</xsl:stylesheet>
我试图通过阻止 <xs:sequence>
的排序来改变行为,但这没有用。
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*[not(local-name()='sequence')]">
<xsl:sort select="name()" />
<xsl:sort select="@*" order="ascending" data-type="text" />
<xsl:sort select="." />
</xsl:apply-templates>
<xsl:apply-templates select="*[local-name()='sequence']"/>
</xsl:copy>
除了 <xs:sequence>
的直系子代之外,我如何将这些规则应用于所有对象?
非常感谢。
如果您不希望 xsl:sequence
的子项被排序,您应该为此添加一个优先于通用模板的特定模板。
<xsl:template match="xs:sequence">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
这将要求您在样式表中声明 xs
命名空间前缀。
试试这个 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes" omit-xml-declaration="no" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()">
<xsl:sort select="name()" />
<xsl:sort select="@*" order="ascending" data-type="text" />
<xsl:sort select="." />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="xs:sequence">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>