如何用xslt替换命名空间uri



如何替换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>

最新更新