我正在使用XSLT将传入的Web服务调用从旧版本转换为新版本的XML。在此版本更改中,它意味着将元素从父项复制到特定位置的多个子项,并更改定义Web服务版本的XML的名称空间。
我差不多了,但我无法让复制的节点更改为新的命名空间。
旧XML:
<n:request xmlns:n="mynamespace2">
<n:element>
<n:id>
<!-- ... -->
</n:id>
<n:source>
<n:aaa><!-- ... --></n:aaa>
<n:copyme>
<n:something attr="value"/>
</n:copyme>
<n:bbb><!-- ... --></n:bbb>
<!-- ... -->
</n:source>
<n:ccc/>
<n:target x="1">
<n:ddd>text</n:ddd>
<n:eee>text</n:eee>
<n:fff><!-- ... --></n:fff>
<!-- many nodes -->
</n:target>
<n:target x="2">
<n:ddd>text</n:ddd>
<n:eee>text</n:eee>
<n:fff><!-- ... --></n:fff>
<!-- many nodes -->
</n:target>
</n:element>
</n:request>
我需要在copyme
之后将target
及其所有子项复制到每个eee
,然后将其从原始位置移除。
我的XSLT:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myns2="mynamespace2"
xmlns:myns3="mynamespace3"
version="1.0">
<xsl:param name="myns2Param">mynamespace2</xsl:param>
<xsl:param name="myns3Param">mynamespace3</xsl:param>
<!-- identity -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- copy the desired node to each child -->
<xsl:template match="/myns2:request/myns2:element/myns2:target">
<xsl:element name="{local-name()}" namespace="{$myns3Param}">
<xsl:apply-templates select="@*|myns2:ddd|myns2:eee" />
<xsl:copy-of select="../myns2:source/myns2:copyme" />
<xsl:apply-templates select="node()[not(self::myns2:ddd or self::myns2:eee)]" />
</xsl:element>
</xsl:template>
<!-- remove original node -->
<xsl:template match="/myns2:request/myns2:element/myns2:source/myns2:copyme" />
<!-- change namespace -->
<xsl:template match="@myns2:*">
<xsl:attribute name="{local-name()}" namespace="{$myns3Param}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="myns2:*">
<xsl:element name="{local-name()}" namespace="{$myns3Param}">
<xsl:apply-templates select="node()|@*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
实际上,这是输出:
<request xmlns="mynamespace3">
<element>
<id>
<!-- ... -->
</id>
<source>
<aaa><!-- ... --></aaa>
<bbb><!-- ... --></bbb>
<!-- ... -->
</source>
<ccc/>
<target x="1">
<ddd>text</ddd>
<eee>text</eee>
<n:copyme xmlns:n="mynamespace2" xmlns:ns1="mynamespace2">
<n:something attr="value"/>
</n:copyme>
<fff><!-- ... --></fff>
<!-- many nodes -->
</target>
<target x="2">
<ddd>text</ddd>
<eee>text</eee>
<n:copyme xmlns:n="mynamespace2" xmlns:ns1="mynamespace2">
<n:something attr="value"/>
</n:copyme>
<fff><!-- ... --></fff>
<!-- many nodes -->
</target>
</element>
</request>
这几乎是正确的,但原始的namespace2
仍然存在于复制的元素中。我找了一种方法解决这个问题,但没有任何效果。我该如何修复这个命名空间?
XSLT实施:Saxon-HE 9.5.0.2
答案 0 :(得分:2)
由于您使用的是XSLT 2.0,因此可以使用<xsl:copy-of select="..." copy-namespaces="no"/>
这将摆脱冗余的命名空间。如果您确实需要将元素移动到不同的命名空间,则不能使用xsl:copy-of
并且应该执行显式递归下降,以复制元素和属性,但不复制命名空间(example here)。