使用XSLT 1.0的命名空间输出导致问题

时间:2010-10-12 00:50:38

标签: xml xslt namespaces xslt-1.0

我正在使用XSLT 1.0来转换某些XML。

我不太确定解释这个的最好方法,所以会使用一些例子。

我的输入XML包含一个使用xsi:type声明的特化。请参阅Payload节点:

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

当我通过我的XSLT发送它时(让我们假设一对一的副本),我得到以下输出

<ns0:RootNode xmlns:ns0="namespace1" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode xmlns:ns1="namespace2">Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

请注意,ns1名称空间已附加到有效内容节点中的各个节点。在大多数情况下,这很好,但是我需要更早地发生声明,即在根节点上,因为它使有效负载节点上的xsi:type定义无效,因为此时序列化程序不知道ns1名称空间,这会阻止正确解析下游。

我可以做些什么来强制此命名空间稍早输出?

编辑过的XSLT代码:

  <!-- Replace The ESBMessage node with the SOAP method -->
  <xsl:template match="s1:ESBMessage" mode="copy">
    <s0:SendESBMessage>
      <s0:msg>
        <xsl:apply-templates select="*" mode="copy"/>
      </s0:msg>
    </s0:SendESBMessage>
  </xsl:template>

  <!-- Generic Copy -->
  <xsl:template match="*" mode="copy">
    <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates mode="copy"/>
    </xsl:element>
  </xsl:template>

1 个答案:

答案 0 :(得分:1)

  

注意ns1名称空间已经存在   附加到各个节点   在有效负载节点内。在多数情况下   这很好,但我需要   那个宣言要早点发生,   即在根节点上,因为它是   xsi:有效负载上的类型定义   节点无效,因为此时   序列化器不知道   ns1名称空间,阻止正确   解析下游。

     

如何强制使用此命名空间   要早一点输出?

您可以做一些非常简单的事情:向我们展示您的代码

您的声明“简单副本”丢失了顶级节点的名称空间之一,对于以下两个“简单副本”不适用:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

结果相同

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

这是第二个“简单副本”:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

结果再次与源XML文档相同