使用XSLT对复杂XML进行排序
我有一个复杂的xml结构,新的xml文件不断以这种方式创建。 我正试图把文件按字母顺序排序。 我可以对配置类型进行排序,但我还想对其中的“部分”和“参数”进行排序 XML输入使用XSLT对复杂XML进行排序,xml,sorting,xslt,Xml,Sorting,Xslt,我有一个复杂的xml结构,新的xml文件不断以这种方式创建。 我正试图把文件按字母顺序排序。 我可以对配置类型进行排序,但我还想对其中的“部分”和“参数”进行排序 XML输入 预期的XML输出 这是我的XSLT: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl
预期的XML输出
这是我的XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates/>
</Document>
</xsl:template>
<xsl:template match="Configurations">
<xsl:copy>
<xsl:for-each select="Configuration" >
<xsl:sort select="@type"/>
<xsl:copy-of select="." />
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="Configurations/Configuration/Section">
<xsl:copy>
<xsl:for-each select="Parameter" >
<xsl:sort select="@name"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="Adaptors">
<xsl:copy>
<xsl:for-each select="Adaptor">
<xsl:sort select="@type"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在您的尝试中,如果您仅将
应用模板
与排序
一起使用,则每个使用,然后使用副本
和应用模板
,这会导致问题,也就是说,将代码替换为
<xsl:for-each select="Configuration" >
<xsl:sort select="@type"/>
<xsl:copy-of select="." />
<xsl:apply-templates select="."/>
</xsl:for-each>
使用一个模板处理所有此类元素。和附加的身份转换模板
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
应该足够了
以下是完整的示例:
<?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"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[*/@type]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@type"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*[*/@name]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
它转变
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Adaptors>
<Adaptor type="TypeB">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Adaptor>
<Adaptor type="TypeA">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Adaptor>
</Adaptors>
<Configurations>
<Configuration type="TypeB">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Configuration>
<Configuration type="TypeA">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Configuration>
</Configurations>
</Document>
进入
输出应该是什么样子?您能提供一个示例吗?显然,在同一输入上执行复制
然后应用模板
的代码是错误的,这个答案解决了这个问题。但是答案可以理解为建议,永远不要将xsl:for-each
与xsl:sort
一起使用。我不确定这是不是有意的,但这不是我会给出的建议。@MichaelKay,对不起,这句话的意思是介绍如何更正发布代码中的问题,而不是一般性的建议。我将尝试重写它,以明确该语句引用了问题代码中采用的方法。我对这些进行了很好的排序,但我仍然坚持对每个“配置”和“适配器”部分中的“部分”和“参数”进行排序。@skaliam,我添加了一个模板来展示如何扩展该方法,以便按@name
对其他元素进行排序。如果你仍然有问题,那么编辑你的问题并提供一个简短但无序的样本和你想要的相应结果。@ SkAlAM,如果答案解决了你的问题,然后考虑接受它。
<xsl:template match="*[*/@type]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@type"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[*/@name]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<?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"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[*/@type]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@type"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*[*/@name]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Adaptors>
<Adaptor type="TypeB">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Adaptor>
<Adaptor type="TypeA">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Adaptor>
</Adaptors>
<Configurations>
<Configuration type="TypeB">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Configuration>
<Configuration type="TypeA">
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
</Configuration>
</Configurations>
</Document>
<Document>
<Adaptors>
<Adaptor type="TypeA">
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
</Adaptor>
<Adaptor type="TypeB">
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
</Adaptor>
</Adaptors>
<Configurations>
<Configuration type="TypeA">
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
</Configuration>
<Configuration type="TypeB">
<Section name="SectionA">
<Parameter name="ParameterA"/>
</Section>
<Section name="SectionB">
<Parameter name="ParameterB"/>
</Section>
</Configuration>
</Configurations>
</Document>