通过xslt重新排列包括子节点的xml节点
我有一个xml文档,现在我想将它翻译成另一个具有相同内容但不同元素顺序的xml文档.
原始的xml文档如: <?xml version = "1.0" encoding = "UTF-8"?> <order xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" > <ship> <zipcode>78712</zipcode> <street>1234 Main Street</street> <country>CN</country> <city>Beijing</city> </ship> <items> <quantity>1</quantity> <itemno>1234</itemno> </items> <items> <quantity>3</quantity> <itemno>1235</itemno> </items> <price>456</price> <customer>Tom Hill</customer> </order> 预期的输出xml文档如: <?xml version = "1.0" encoding = "UTF-8"?> <order xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" > <customer>Tom Hill</customer> <ship> <street>1234 Main Street</street> <city>Beijing</city> <zipcode>78712</zipcode> <country>CN</country> </ship> <items> <itemno>1234</itemno> <quantity>1</quantity> </items> <items> <itemno>1235</itemno> <quantity>3</quantity> </items> <price>456</price> </order> 我使用以下xslt文档来翻译它. <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/order"> <xsl:copy> <xsl:copy-of select="customer" /> <xsl:copy-of select="ship" > <xsl:call-template name="TShip" /> </xsl:copy-of> <xsl:copy-of select="items"> <xsl:call-template name="TItems" /> </xsl:copy-of> <xsl:copy-of select="price" /> </xsl:copy> </xsl:template> <xsl:template name="TShip"> <xsl:copy> <xsl:copy-of select="street" /> <xsl:copy-of select="city" /> <xsl:copy-of select="zipcode" /> <xsl:copy-of select="country" /> </xsl:copy> </xsl:template> <xsl:template name="TItems"> <xsl:for-each select="items"> <xsl:copy> <xsl:copy-of select="itemno" /> <xsl:copy-of select="quantity" /> </xsl:copy> </xsl:for-each> </xsl:template> </xsl:stylesheet> 但是,翻译的结果不是我的预期. <?xml version = "1.0" encoding = "UTF-8"?> <order xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" > <customer>Tom Hill</customer> <ship> <zipcode>78712</zipcode> <street>1234 Main Street</street> <country>CN</country> <city>Beijing</city> </ship> <items> <quantity>1</quantity> <itemno>1234</itemno> </items> <items> <quantity>3</quantity> <itemno>1235</itemno> </items> <price>456</price> </order> 它只是按预期顺序制作了第一级节点.所有子节点都保持原始顺序.如何使所有节点的顺序符合我的预期?
xsl:copy-of拷贝所有子节点以及它的子节点都不被评估.
因此,您的TShip和TItems模板甚至从未被评估过. < xsl:copy-of select =“ship”>复制所有< ship> …< / ship>. 对模板的这种修改将证明您的TShip和TItems模板未被调用. <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/order"> <xsl:copy> <xsl:copy-of select="customer" /> <xsl:copy-of select="ship"> <xsl:call-template name="TShip" /> </xsl:copy-of> <xsl:copy-of select="items"> <xsl:call-template name="TItems" /> </xsl:copy-of> <xsl:copy-of select="price" /> </xsl:copy> </xsl:template> <xsl:template name="TShip"> <xsl:copy> <test>TShip called</test> <xsl:copy-of select="street" /> <xsl:copy-of select="city" /> <xsl:copy-of select="zipcode" /> <xsl:copy-of select="country" /> </xsl:copy> </xsl:template> <xsl:template name="TItems"> <xsl:for-each select="items"> <xsl:copy> <test>TItems called</test> <xsl:copy-of select="itemno" /> <xsl:copy-of select="quantity" /> </xsl:copy> </xsl:for-each> </xsl:template> </xsl:stylesheet> 请注意,输出不包含< test>我添加的元素. 你需要做的是递归隐式复制.通常xsl:copy,xsl:copy-of和xsl:for-each是错误的xsl模板设计的标志 – xsl:template和xsl:apply-template与身份转换的处理方式很少有问题. 我就是这样做的: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="UTF-8" indent="yes" method="xml" /> <xsl:template match="order"> <xsl:copy> <!-- copy all attributes; maybe you don't want this --> <xsl:apply-templates select="@*" /> <!-- copy some elements in a specific order --> <xsl:apply-templates select="customer" /> <xsl:apply-templates select="ship" /> <xsl:apply-templates select="items" /> <xsl:apply-templates select="price" /> <!-- now copy any other children that we haven't explicitly reordered; again,possibly this is not what you want --> <xsl:apply-templates select="*[not(self::customer or self::ship or self::items or self::price)]"/> </xsl:copy> </xsl:template> <xsl:template match="ship"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates select="street" /> <xsl:apply-templates select="city" /> <xsl:apply-templates select="zipcode" /> <xsl:apply-templates select="country" /> <xsl:apply-templates select="*[not(self::street or self::city or self::zipcode or self::country)]"/> </xsl:copy> </xsl:template> <xsl:template match="items"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates select="itemno" /> <xsl:apply-templates select="quantity" /> <xsl:apply-templates select="*[not(self::itemno or self::quantity)]"/> </xsl:copy> </xsl:template> <!-- this is the identity transform: it copies everything that isn't matched by a more specific template --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> 请注意,此模板设计对源XML结构的假设少了很多.它也更容易改变:例如,如果你想沉默或重命名一个本身可能有子元素的特定元素,你只需添加一个与该元素匹配的新xsl:模板,做你需要做的任何事情,和xsl:对孩子们应用模板. 你应该learn more about this XSLT pattern,因为它非常通用,并且使模板创作更加乏味,而且你的模板更不易碎. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |