当前位置: 首页 > 知识库问答 >
问题:

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

柴俊捷
2023-03-14

我正在尝试使用源代码xml的脚本,其结果可在下面的小提琴工具链接中获得

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脚本面临两个问题,

>

  • XSL在转义时从根目录到子目录包含一个名称空间。xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance,但在转义

    根目录中的名称空间并非全部复制到结果XML中。xsi:schemaLocation=”http://mspdv170.us.oracle.com:7779/rib-父级

    请分享任何提示,因为我对XSLT非常陌生。XSL版本是3.0,在我正在做的项目中使用SAXON 9.6引擎。


  • 共有1个答案

    南宫星波
    2023-03-14

    Saxon 9.6的行为似乎是Saxon 10.2中仍然存在的一个bug,我在https://saxonica.plan.io/boards/3/topics/8011这导致了bug问题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:schemaLocationmissing,这是一个您忘记复制的属性;使用

       <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

     类似资料:
    • 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变化。 “内部模块”现在称做“命名空间”。 “外部模块”现在则简称为“模块”,这是为了与ECMAScript 2015里的术语保持一致,(也就是说 module X { 相当于现在推荐的写法 namespace X {)。 这篇文章描述了如何在TypeScript里使用命名空间(之前叫做“内部模块”)来组织你的代码

    • Let the word of Christ dwell in you richly in all wisdom; teaching and admonishing one another in psalms and hymns and spiritual songs, singing with grrace in your hearts tto the Lord. And whatsoever

    • 客户端有许多“命名空间”,通常是一些公开的可管理功能。命名空间对应 Elasticsearch 中各种可管理的 endpoint。下面是全部的命名空间: **命名空间** **功能** `indices()` 索引数据统计和显示索引信息 `nodes()` 节点数据统计和显示节点信息 `cluster()` 集群数据统计和显示集群信息 `snapshot()` 对集群和索引进行拍摄快照或恢复数据

    • 命名空间 由于 js 环境极少命名空间管理模块, namespace 相对陌生, 比如有这样的文件结构, src/ demo/ core.cljs 可以看到 core.cljs 的路径就是: src/demo/core.cljs 注意 JVM 环境有个 classpath 的环境变量, 用于判断怎样查找源码, classpath 对应多个路径, 也可能是 jar 包, 而 jar 包中

    • 命名空间,英文名字:namespaces 在研习命名空间以前,请打开在python的交互模式下,输入:import this >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than

    • Swoole提供了完善的进程管理机制,当Worker进程异常退出,如发生PHP的致命错误、被其他程序误杀,或达到max_request次数之后正常退出。主进程会重新拉起新的Worker进程。 Worker进程内可以像普通的apache+php或者php-fpm中写代码。不需要像Node.js那样写异步回调的代码。 主进程内的回调函数: onStart onShutdown onTimer Work