我有一个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>
Run Code Online (Sandbox Code Playgroud)
预期的输出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>
Run Code Online (Sandbox Code Playgroud)
我使用以下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>
Run Code Online (Sandbox Code Playgroud)
但是,翻译的结果不是我的预期.翻译结果xml:
<?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>
Run Code Online (Sandbox Code Playgroud)
它只是按预期顺序制作了第一级节点.所有子节点都保持原始顺序.如何使所有节点的顺序符合我的预期?
Fra*_*ila 10
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>
Run Code Online (Sandbox Code Playgroud)
请注意,输出并没有包含<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>
Run Code Online (Sandbox Code Playgroud)
请注意,此模板设计对源XML结构的假设少了很多.它也更容易改变:例如,如果你想沉默或重命名一个本身可能有孩子的特定元素,你只需要添加一个xsl:template匹配该元素的新元素,做你需要做的任何事情,以及xsl:apply-templates孩子们.
您应该了解有关此XSLT模式的更多信息,因为它非常通用,并且使模板创作更加繁琐,并且您的模板更不易碎.
| 归档时间: |
|
| 查看次数: |
7194 次 |
| 最近记录: |