Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在根元素上用XSLT替换多个命名空间_Xslt_Namespaces - Fatal编程技术网

在根元素上用XSLT替换多个命名空间

在根元素上用XSLT替换多个命名空间,xslt,namespaces,Xslt,Namespaces,我有以下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" xml

我有以下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以这种方式更改名称空间吗


感谢您对这一转变的任何建议

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

应用于提供的XML文档时

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

生成所需的正确结果

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

我认为Dimitre充分证明了我的观点,即任何XSLT解决方案都将比在使用XSLT处理XML文档之前在XML文档的第一行进行文本替换复杂得多

不同名称空间的元素在技术上是完全不同的元素。因为XML技术认为它们是不同的,所以实际上必须处理每一个,即使它们在输出时看起来是相同的


具体操作方式取决于您使用的平台,但简单的“查找
http://a/1
并将其替换为
http://a/2
应该为每个名称空间执行此操作。

是否有理由不在第一行进行简单的文本替换?这似乎比尝试使用XSLT要容易得多。我必须在XML结构中做更多的更改,但这是我唯一无法解决的任务。转换是模型升级的一部分。你不能两者都做吗?用文本replace更改名称空间,然后应用XSLT完成其余的工作?考虑到您正在有效地更改文档中大多数元素(如果不是所有元素的话)的名称空间,在一个XSLT中完成所有操作的XSLT可能要复杂得多。我认为使用单个XSLT会更容易,但如果更简单、更有效,我也可以在应用XSLT之前使用文本替换。但是,用XSLT以这种方式更改名称空间是否可行?这取决于XML的来源。如果它只是存储为文本,那么在将其实际用作XML之前,没有任何东西可以阻止您以任何方式修改该文本。