如何替换XML消息中一个或多个元素的名称空间uri,而不事先知道发送者将任意使用的名称空间前缀?
我知道这个问题的形式已经被问过很多次了,但是我找到的每个答案(在这里和其他网站)都以确切了解前缀为前提。根据定义,前缀是任意的,解决这个问题不需要对所使用的前缀有深入的了解。
我有一个解决方案,但它会在输出中产生我不需要的垃圾。简单的输入:
<?xml version="1.0" encoding="UTF-8"?>
<myThing xmlns:s="http://tempuri3.org/">
<s:thisThing>
<thatThing xmlns="http://cheapCookies.org/"/>
<anotherThing xmlns="http://kingkong.org">
<thisThing/>
</anotherThing>
</s:thisThing>
</myThing>
这是XSLT:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="sourceNamespace" select="'http://tempuri3.org/'" />
<xsl:param name="targetNamespace" select="'http://tempuri.org'"/>
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="node() | @*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="namespace-uri() = $sourceNamespace">
<xsl:element name="{name()}" namespace="{$targetNamespace}">
<xsl:apply-templates select="node() | @*"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="identity"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这是上面XSLT的输出:
<?xml version="1.0" encoding="utf-8"?>
<myThing xmlns:s="http://tempuri3.org/">
<s:thisThing xmlns:s="http://tempuri.org">
<thatThing xmlns="http://cheapCookies.org/" xmlns:s="http://tempuri3.org/"/>
<anotherThing xmlns="http://kingkong.org" xmlns:s="http://tempuri3.org/">
<thisThing/>
</anotherThing>
</s:thisThing>
</myThing>
这是期望的输出:
<?xml version="1.0" encoding="utf-8"?>
<myThing xmlns:s="http://tempuri.org/">
<s:thisThing>
<thatThing xmlns="http://cheapCookies.org/"/>
<anotherThing xmlns="http://kingkong.org">
<thisThing/>
</anotherThing>
</s:thisThing>
</myThing>
我知道源和目标命名空间uri,
那么你应该这样做:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="http://tempuri3.org/"
exclude-result-prefixes="old">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="old:*">
<xsl:element name="{local-name()}" namespace="http://tempuri.org">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
根据所使用的确切处理器,结果可能略有不同。例如,Saxon 6.5将返回:
<?xml version="1.0" encoding="UTF-8"?>
<myThing xmlns:s="http://tempuri3.org/">
<thisThing xmlns="http://tempuri.org">
<thatThing xmlns="http://cheapCookies.org/"/>
<anotherThing xmlns="http://kingkong.org">
<thisThing/>
</anotherThing>
</thisThing>
</myThing>