如何用xslt替换命名空间uri

时间:2014-06-30 15:17:36

标签: xml xslt

如何在不事先知道发件人可以任意使用的名称空间前缀的情况下替换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>

1 个答案:

答案 0 :(得分:2)

  

我知道源和目标命名空间uris,

然后你应该这样做:

<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>