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>
请注意,输出确实not包含<test>
我添加的元素。
你需要做什么是递归隐式复制。通常xsl:copy
, xsl:copy-of
and xsl:for-each
是 xsl 模板设计不良的标志——很少有问题会导致xsl:template
and 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:template
与该元素匹配,做任何你需要做的事情,并且xsl:apply-templates
在孩子们身上。
你应该了解有关此 XSLT 模式的更多信息因为它的用途非常广泛,可以使模板创作变得不那么繁琐,并且您的模板也不那么脆弱。