我希望改变一些 XML元素的顺序. XML很复杂并且由一个单独的进程生成 – 我不需要更改它,所以我希望使用XSLT来纠正元素顺序. 我不是一个XSLT专家(!)所以我找了一些片段,发现了一些东西
我不是一个XSLT专家(!)所以我找了一些片段,发现了一些东西,只需稍微改动以适应我的情况,几乎可以工作.我目前使用的最佳版本以正确的顺序输出元素,但删除了所有属性.
我创建了一个更简单的xml和相应的xsl以及我的问题的相关功能.
这是(虚拟)示例xml:
<?xml version="1.0" encoding="UTF-8"?> <Companies xmlns="company:fruit:ns" Version="1.0"> <Description>Some example companies and fruit shipments</Description> <Company CompanyId="Acme"> <Description>Some example shipments</Description> <Shipment Id="ABC"> <Description>Some apples</Description> <Fruit> <Apples>10</Apples> </Fruit> </Shipment> <Shipment Id="DEF"> <Description>Some oranges and pears</Description> <Fruit> <Oranges>20</Oranges> <Pears>20</Pears> </Fruit> </Shipment> <Shipment Id="JKL"> <Description>Empty</Description> <Fruit/> </Shipment> <Fruit/> </Company> <Fruit/> </Companies>
问题是在Company-Description元素之后应该有一个Company-Fruit元素(而不是它遵循所有Shipment元素),并且在Companies-Description元素之后应该有一个Companies-Fruit元素(而不是它遵循所有公司 – 公司要素).我使用以下xsl转换来更正元素排序:
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xpath-default-namespace="company:fruit:ns"> <!-- See http://xsltbyexample.blogspot.com/2008/02/re-arrange-order-of-elements-in-xml.html --> <xsl:output omit-xml-declaration="no" indent="yes" method="xml" encoding="utf-8"/> <xsl:strip-space elements="*"/> <xsl:template match="*"> <xsl:apply-templates select="self::*" mode="copy"/> </xsl:template> <xsl:template match="Company/Description"> <xsl:message>Matched Company Description</xsl:message> <xsl:apply-templates select="self::*" mode="copy"/> <xsl:apply-templates select="../Fruit" mode="copy"/> </xsl:template> <xsl:template match="Companies/Description"> <xsl:message>Matched Companies Description</xsl:message> <xsl:apply-templates select="self::*" mode="copy"/> <xsl:apply-templates select="../Fruit" mode="copy"/> </xsl:template> <xsl:template match="Company/Fruit"/> <xsl:template match="Companies/Fruit"/> <xsl:template match="*" mode="copy"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
生成的xml具有正确的顺序,但大部分属性已被删除:
<?xml version="1.0" encoding="utf-8"?> <Companies xmlns="company:fruit:ns"> <Description>Some example companies and fruit shipments</Description> <Fruit/> <Company> <Description>Some example shipments</Description> <Fruit/> <Shipment> <Description>Some apples</Description> <Fruit> <Apples>10</Apples> </Fruit> </Shipment> <Shipment> <Description>Some oranges and pears</Description> <Fruit> <Apples>20</Apples> <Pears>20</Pears> </Fruit> </Shipment> <Shipment> <Description>Empty</Description> <Fruit/> </Shipment> </Company> </Companies>
我欢迎来自XSLT专家的任何建议!
几乎所有输入都保持不变的转换最好用身份模板开始.<xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*" /> </xsl:copy> </xsl:template>
然后相应地覆盖该模板.
<!-- throw away <Fruit> elements, initially - they are handled separately --> <xsl:template match="Company/Fruit | Companies/Fruit" /> <!-- re-build <Company> and <Companies> in the correct order --> <xsl:template match="Company | Companies"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:copy-of select="Fruit" /> <xsl:apply-templates select="node()" /> </xsl:copy> </xsl:template>
然后你就完成了.