xsl 命名空间从根复制到子节点,copy-namespaces="no" 不工作(xslt 3.0 版本)

xsl namespace from root copied to child node ,copy-namespaces="no" not working (xslt 3.0 version)

我正在尝试使用源 xml 的脚本,结果可在下面的 fiddle 工具 link

中找到

https://xsltfiddle.liberty-development.net/jxN9PRK/4

来源XML:

<root xmlns="http://www.oracle.com/retail/integration/rib/RibMessages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mspdv170.us.oracle.com:7779/rib-func-artifact/integration/xsd/RibMessages.xsd">
   <parent>test</parent>
   <parentdtl>
   <child xmlns="http://test.com">
       <element1>1</element1>
   </child>   
   </parentdtl>
   <outer>T</outer>
</root> 

使用的 XSL 脚本:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://mspdv170.us.oracle.com:7779/rib-func-artifact/integration/xsd/RibMessages.xsd"
    exclude-result-prefixes="#all"
    version="3.0">
  <xsl:template match="*">
        <xsl:variable name="copy-sans-namespaces" as="element()">
            <xsl:copy-of select="." copy-namespaces="no"/>
        </xsl:variable>
        <xsl:variable name="ser-params" as="element()">
            <output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
                <output:omit-xml-declaration value="yes" />
            </output:serialization-parameters>
        </xsl:variable>
        <xsl:value-of select="serialize($copy-sans-namespaces, $ser-params)" />
    </xsl:template>
   <xsl:template match="*:root|*:parent|*:parentdtl|*:outer">
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template> 
</xsl:stylesheet>

预期输出:

<?xml version="1.0" encoding="UTF-8"?><root xmlns="http://www.oracle.com/retail/integration/rib/RibMessages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mspdv170.us.oracle.com:7779/rib-func-artifact/integration/xsd/RibMessages.xsd">
   <parent>test</parent>
   <parentdtl>
   &lt;child xmlns="http://test.com"&gt;
       &lt;element1&gt;1&lt;/element1&gt;
   &lt;/child&gt;   
   </parentdtl>
   <outer>T</outer>
</root>

相反,我收到了以下结果

<?xml version="1.0" encoding="UTF-8"?><root xmlns="http://www.oracle.com/retail/integration/rib/RibMessages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <parent>test</parent>
   <parentdtl>
   &lt;child xmlns="http://test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
       &lt;element1&gt;1&lt;/element1&gt;
   &lt;/child&gt;   
   </parentdtl>
   <outer>T</outer>
</root>

在 XSL 脚本中遇到两个问题,

  1. XSL 在转义时包括从根到其子名称空间之一。 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ,但是在转义 <child> 节点时不应包括在内,但 <child> 节点的原始名称空间应该是保留在转换中。

  2. 根中的命名空间并未全部复制到结果中XML。 xsi:schemaLocation="http://mspdv170.us.oracle.com:7779/rib-func-artifact/integration/xsd/RibMessages.xsd" 在结果 xml.

    的父 <root> 节点中丢失

请分享任何指示,因为我是 XSLT 的新手。 XSL 版本是 3.0 并且在我正在处理的项目中使用 SAXON 9.6 引擎。

您在 Saxon 9.6 中获得的行为似乎是 Saxon 10.2 中仍然存在的错误,我在 https://saxonica.plan.io/boards/3/topics/8011 which lead to the bug issue https://saxonica.plan.io/issues/4793.

中查询过它

作为一种变通方法,我想您需要将元素推送到一个使用 xsl:element 进行复制的节点,避免命名空间复制:

  <xsl:template match="*" mode="strip-in-scope-namespaces">
      <xsl:element name="{name()}" namespace="{namespace-uri()}">
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates mode="#current"/>
      </xsl:element>
  </xsl:template>

  <xsl:template match="*">
        <xsl:variable name="copy-sans-namespaces" as="element()">
            <xsl:apply-templates select="." mode="strip-in-scope-namespaces"/>
        </xsl:variable>
      
        <xsl:variable name="ser-params" as="element()">
            <output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
                <output:omit-xml-declaration value="yes" />
            </output:serialization-parameters>
        </xsl:variable>

        <xsl:value-of select="serialize($copy-sans-namespaces, $ser-params)" />
    </xsl:template>

https://xsltfiddle.liberty-development.net/jxN9PRK/5

至于xsi:schemaLocation缺失,那是你忘记复制的属性;使用

   <xsl:template match="*:root|*:parent|*:parentdtl|*:outer">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

https://xsltfiddle.liberty-development.net/jxN9PRK/6