我有以下XML文档
<a:rootElement xmlns:a="http://a/1" xmlns:b="http://b/1" xmlns:c="http://c/1">
<child1 type="b:type"/>
<child2 type="c:type"/>
</a:rootElement>
现在我想更改名称空间的URI,以便得到以下结果
<a:rootElement xmlns:a="http://a/2" xmlns:b="http://b/2" xmlns:c="http://c/2">
<child1 type="b:type"/>
<child2 type="c:type"/>
</a:rootElement>
别的什么都不应该改变。我尝试使用以下样式表。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:a="http://a/2"
xmlns:b="http://b/2"
xmlns:c="http://c/2" >
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="document('')/*/namespace::*[name()='a']"/>
<xsl:copy-of select="document('')/*/namespace::*[name()='b']"/>
<xsl:copy-of select="document('')/*/namespace::*[name()='c']"/>
<xsl:copy-of select="node()|@*"/>
</xsl:element>
</xsl:template>
我得到以下错误输出。
<a_0:rootElement xmlns:a_0="http://a/1" xmlns:a="http://a/2" xmlns:b="http://b/2" xmlns:c="http://c/2">
<child1 type="b:type" xmlns:a="http://a/1" xmlns:b="http://b/1" xmlns:c="http://c/1"/>
<child2 type="c:type" xmlns:a="http://a/1" xmlns:b="http://b/1" xmlns:c="http://c/1"/>
</a_0:rootElement>
我也尝试了其他一些方法,但也没有所需的输出。是否可以使用XSLT以这种方式更改名称空间?
感谢您的任何建议
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a1="http://a/1"
xmlns:b1="http://b/1"
xmlns:c1="http://c/1"
xmlns:a="http://a/2"
xmlns:b="http://b/2"
xmlns:c="http://c/2"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vDoc" select="document('')/*"/>
<xsl:variable name="vnsA" select="$vDoc/namespace::*[name()='a1']"/>
<xsl:variable name="vnsB" select="$vDoc/namespace::*[name()='b1']"/>
<xsl:variable name="vnsC" select="$vDoc/namespace::*[name()='c1']"/>
<xsl:variable name="vnsA2" select="$vDoc/namespace::*[name()='a']"/>
<xsl:variable name="vnsB2" select="$vDoc/namespace::*[name()='b']"/>
<xsl:variable name="vnsC2" select="$vDoc/namespace::*[name()='c']"/>
<xsl:template match="*">
<xsl:variable name="vNS" select="namespace-uri()"/>
<xsl:variable name="vnewNS">
<xsl:choose>
<xsl:when test="$vNS = $vnsA">
<xsl:value-of select="$vnsA2"/>
</xsl:when>
<xsl:when test="$vNS = $vnsB">
<xsl:value-of select="$vnsB2"/>
</xsl:when>
<xsl:when test="$vNS = $vnsC">
<xsl:value-of select="$vnsC2"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:element name="{name()}" namespace="{$vnewNS}">
<xsl:copy-of select=
"namespace::*[not(contains('|a|b|c|', concat('|', name(), '|')))]
"/>
<xsl:copy-of select="namespace::*[name() = 'a' and not(. = $vnsA)]"/>
<xsl:copy-of select="namespace::*[name() = 'b' and not(. = $vnsB)]"/>
<xsl:copy-of select="namespace::*[name() = 'c' and not(. = $vnsC)]"/>
<xsl:if test="namespace::*[name() = 'a' and . = $vnsA]">
<xsl:copy-of select="$vnsA2"/>
</xsl:if>
<xsl:if test="namespace::*[name() = 'b' and . = $vnsB]">
<xsl:copy-of select="$vnsB2"/>
</xsl:if>
<xsl:if test="namespace::*[name() = 'c' and . = $vnsC]">
<xsl:copy-of select="$vnsC2"/>
</xsl:if>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<a:rootElement
xmlns:a="http://a/1"
xmlns:b="http://b/1"
xmlns:c="http://c/1">
<child1 type="b:type"/>
<child2 type="c:type"/>
</a:rootElement>
生成想要的正确结果:
<a:rootElement xmlns:a="http://a/2" xmlns:b="http://b/2" xmlns:c="http://c/2">
<child1 type="b:type"/>
<child2 type="c:type"/>
</a:rootElement>
答案 1 :(得分:0)
我认为Dimitre充分证明了我的观点,即在使用XSLT处理它之前,任何XSLT解决方案都比在XML文档的第一行简单地进行文本替换要复杂得多。
不同命名空间的元素在技术上是完全不同的元素。因为XML技术认为它们是不同的,所以你实际上必须处理和处理每一个,即使它们在输出时看起来是相同的。
你究竟是如何做的取决于你正在使用的平台,但是对于每个命名空间来说,一个简单的'找到第一次出现的http://a/1
并将其替换为http://a/2
就可以完成这项工作。 / p>