【问题标题】:Remove xmlns soap attribute from xml using xslt使用 xslt 从 xml 中删除 xmlns soap 属性
【发布时间】:2016-05-30 11:06:18
【问题描述】:

我正在尝试将 soap 消息复制到自定义 xml(从 Envelope、Header、Body 中删除 soap 命名空间并从 ResponseHeader 元素中删除命名空间前缀,一切都很好,期望 ResponseHeader 和 ResponseData 元素中有一个 xmlns:soap 命名空间。

输入:

<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http:test/201/2"
xmlns:m0="http:test/201/3"
xmlns:ns0="http:test/201/4"
xmlns:ns2="http:test/201/5"
xmlns:ns1="http:test/201/6"
xmlns:ns3="http:test/201/7"
xmlns:ns6="http:test/201/8"
xmlns:ns4="http:test/201/9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<soap:Header>
<ns0:ResponseHeader>
<ns:Env>Dev</ns:Env>
<ns:Version>1</ns:Version>
<ns:Server>
<ns:Name>NAME</ns:Name>
</ns0:ResponseHeader>
</soap:Header>
<soap:Body>
<ns2:ResponseData>
<ns2:Employee />
<ns2:MessageList>
<ns2:Message>
<ns4:Type>new</ns4:Type>
<ns4:Code>1</ns4:Code>
<ns4:Source>contract</ns4:Source>
<ns4:Description>new hire</ns4:Description>
</ns2:Message>
</ns2:Employee>
</ns2:ResponseData>
</soap:Body>
</soap:Envelope>

预期输出:

<Envelope   
xmlns:ns="http:test/201/2"
xmlns:m0="http:test/201/3"
xmlns:ns0="http:test/201/4"
xmlns:ns2="http:test/201/5"
xmlns:ns1="http:test/201/6"
xmlns:ns3="http:test/201/7"
xmlns:ns6="http:test/201/8"
xmlns:ns4="http:test/201/9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<Header>
<ResponseHeader>
<ns:Env>Dev</ns:Env>
<ns:Version>1</ns:Version>
<ns:Server>
<ns:Name>NAME</ns:Name>
</ResponseHeader>
</Header>
<Body>
<ns2:ResponseData>
<ns2:Employee />
<ns2:MessageList>
<ns2:Message>
<ns4:Type>new</ns4:Type>
<ns4:Code>1</ns4:Code>
<ns4:Source>contract</ns4:Source>
<ns4:Description>new hire</ns4:Description>
</ns2:Message>
</ns2:Employee>
</ns2:ResponseData>
</Body>
</Envelope>

我的 Xslt:

<xsl:stylesheet version="2.0" extension-element-prefixes="dp" exclude-result-prefixes="soap ns3 snss  ns0 ns1 ns4 #default" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http:test/201/2"
xmlns:m0="http:test/201/3"
xmlns:ns0="http:test/201/4"
xmlns:ns2="http:test/201/5"
xmlns:ns1="http:test/201/6"
xmlns:ns3="http:test/201/7"
xmlns:ns6="http:test/201/8"
xmlns:ns4="http:test/201/9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
  <xsl:output method="xml" version="1.0" indent="no"/>
  <xsl:template match="node()|@*" exclude-result-prefixes="#all">

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

 <xsl:template match="soap:*" exclude-result-prefixes="#all">
  <xsl:element name="{local-name()}">
    <xsl:copy-of select="namespace::*[not(. = namespace-uri(..))]"/>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>
  <xsl:template match="tns:ResponseData" exclude-result-prefixes="#all">
 <ResponseHeader>
    <xsl:copy-of select="namespace::*[not(. = namespace-uri(..))]"/>
    <xsl:apply-templates select="node()|@*"/>
  </ResponseHeader>
 </xsl:template> 

</xsl:stylesheet>

获取输出:

<Envelope

xmlns:ns="http:test/201/2"
xmlns:m0="http:test/201/3"
xmlns:ns0="http:test/201/4"
xmlns:ns2="http:test/201/5"
xmlns:ns1="http:test/201/6"
xmlns:ns3="http:test/201/7"
xmlns:ns6="http:test/201/8"
xmlns:ns4="http:test/201/9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<Header>
<ResponseHeader xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<ns:Env>Dev</ns:Env>
<ns:Version>1</ns:Version>
<ns:Server>
<ns:Name>NAME</ns:Name>
</ResponseHeader>
</Header>
<Body>
<ns2:ResponseData xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<ns2:Employee />
<ns2:MessageList>
<ns2:Message>
<ns4:Type>new</ns4:Type>
<ns4:Code>1</ns4:Code>
<ns4:Source>contract</ns4:Source>
<ns4:Description>new hire</ns4:Description>
</ns2:Message>
</ns2:Employee>
</ns2:ResponseData>
</Body>
</Envelope>

请帮助如何摆脱 xmlns:soap 属性?

【问题讨论】:

  • 请发布一个格式良好的输入和输出。

标签: xml xslt soap


【解决方案1】:

此解决方案适用于所有 XSLT 版本:1.0、2.0 和 3.0(而且更短):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:x="http:test/201/4">
 <xsl:output omit-xml-declaration="yes"/>

  <xsl:template match="*" priority="1">
    <xsl:element name="{name()}" namespace="{namespace-uri()}">
      <xsl:copy-of select="namespace::*[not(name()='soap')]"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="soap:* | x:ResponseHeader" priority="2">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="namespace::*[not(name()='soap')]"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

当此转换应用于 XML 文档时(格式正确):

<soap:Envelope 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns="http:test/201/2"
xmlns:m0="http:test/201/3"
xmlns:ns0="http:test/201/4"
xmlns:ns2="http:test/201/5"
xmlns:ns1="http:test/201/6"
xmlns:ns3="http:test/201/7"
xmlns:ns6="http:test/201/8"
xmlns:ns4="http:test/201/9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Header>
      <ns0:ResponseHeader>
         <ns:Env>Dev</ns:Env>
         <ns:Version>1</ns:Version>
         <ns:Server/>
         <ns:Name>NAME</ns:Name>
      </ns0:ResponseHeader>
   </soap:Header>
   <soap:Body>
      <ns2:ResponseData>
         <ns2:Employee>
            <ns2:MessageList>
               <ns2:Message>
                  <ns4:Type>new</ns4:Type>
                  <ns4:Code>1</ns4:Code>
                  <ns4:Source>contract</ns4:Source>
                  <ns4:Description>new hire</ns4:Description>
               </ns2:Message>
            </ns2:MessageList>
         </ns2:Employee>
      </ns2:ResponseData>
   </soap:Body>
</soap:Envelope>

产生想要的正确结果:

<Envelope xmlns:ns="http:test/201/2" xmlns:m0="http:test/201/3" 
          xmlns:ns0="http:test/201/4" xmlns:ns2="http:test/201/5" 
          xmlns:ns1="http:test/201/6" xmlns:ns3="http:test/201/7" 
          xmlns:ns6="http:test/201/8" xmlns:ns4="http:test/201/9" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Header>
        <ResponseHeader>
            <ns:Env>Dev</ns:Env>
            <ns:Version>1</ns:Version>
            <ns:Server/>
            <ns:Name>NAME</ns:Name>
        </ResponseHeader>
    </Header>
    <Body>
        <ns2:ResponseData>
            <ns2:Employee>
                <ns2:MessageList>
                    <ns2:Message>
                        <ns4:Type>new</ns4:Type>
                        <ns4:Code>1</ns4:Code>
                        <ns4:Source>contract</ns4:Source>
                        <ns4:Description>new hire</ns4:Description>
                    </ns2:Message>
                </ns2:MessageList>
            </ns2:Employee>
        </ns2:ResponseData>
    </Body>
</Envelope>

【讨论】:

  • *[local-name()='ResponseHeader'] = 不好的做法。应该使用命名空间,而不是忽略。
  • @michael.hor257k,这通常是一个明智的反馈。不过,我不确定ResponseHeader 是否会始终位于该名称空间中——这就是为什么我从字面上实现了结果元素不应位于任何名称空间中的要求。换句话说,这个表达式确实有它自己的用例,我相信当前的问题就是这样一个用例。尽管我相信反映您的反馈会降低解决方案的通用性,但我就是这样做的。还有其他的cmets吗?
【解决方案2】:

您的输入和输出都不是格式正确的 XML。而且您的“XSLT”甚至不是 XSLT 文档!

AFAICT,你想做的事:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns0="http:test/201/4"
exclude-result-prefixes="soap">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*">
    <xsl:copy copy-namespaces="no">
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="soap:* | ns0:ResponseHeader">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="/soap:Envelope">
    <Envelope> 
        <xsl:copy-of select="namespace::*"/>
        <xsl:apply-templates/>
    </Envelope>
</xsl:template>

</xsl:stylesheet>

将此应用于以下格式良好的 XML 输入:

<soap:Envelope 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns="http:test/201/2"
xmlns:m0="http:test/201/3"
xmlns:ns0="http:test/201/4"
xmlns:ns2="http:test/201/5"
xmlns:ns1="http:test/201/6"
xmlns:ns3="http:test/201/7"
xmlns:ns6="http:test/201/8"
xmlns:ns4="http:test/201/9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Header>
      <ns0:ResponseHeader>
         <ns:Env>Dev</ns:Env>
         <ns:Version>1</ns:Version>
         <ns:Server/>
         <ns:Name>NAME</ns:Name>
      </ns0:ResponseHeader>
   </soap:Header>
   <soap:Body>
      <ns2:ResponseData>
         <ns2:Employee>
            <ns2:MessageList>
               <ns2:Message>
                  <ns4:Type>new</ns4:Type>
                  <ns4:Code>1</ns4:Code>
                  <ns4:Source>contract</ns4:Source>
                  <ns4:Description>new hire</ns4:Description>
               </ns2:Message>
            </ns2:MessageList>
         </ns2:Employee>
      </ns2:ResponseData>
   </soap:Body>
</soap:Envelope>

将返回:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns:ns0="http:test/201/4" xmlns:ns="http:test/201/2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:m0="http:test/201/3"
          xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
          xmlns:ns2="http:test/201/5"
          xmlns:ns1="http:test/201/6"
          xmlns:ns3="http:test/201/7"
          xmlns:ns6="http:test/201/8"
          xmlns:ns4="http:test/201/9">
   <Header>
      <ResponseHeader>
         <ns:Env>Dev</ns:Env>
         <ns:Version>1</ns:Version>
         <ns:Server/>
         <ns:Name>NAME</ns:Name>
      </ResponseHeader>
   </Header>
   <Body>
      <ns2:ResponseData>
         <ns2:Employee>
            <ns2:MessageList>
               <ns2:Message>
                  <ns4:Type>new</ns4:Type>
                  <ns4:Code>1</ns4:Code>
                  <ns4:Source>contract</ns4:Source>
                  <ns4:Description>new hire</ns4:Description>
               </ns2:Message>
            </ns2:MessageList>
         </ns2:Employee>
      </ns2:ResponseData>
   </Body>
</Envelope>

请注意,包含最后一个匹配 /soap:Envelope 的模板纯粹是出于美观的原因。如果删除它,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
   <Header>
      <ResponseHeader>
         <ns:Env xmlns:ns="http:test/201/2">Dev</ns:Env>
         <ns:Version xmlns:ns="http:test/201/2">1</ns:Version>
         <ns:Server xmlns:ns="http:test/201/2"/>
         <ns:Name xmlns:ns="http:test/201/2">NAME</ns:Name>
      </ResponseHeader>
   </Header>
   <Body>
      <ns2:ResponseData xmlns:ns2="http:test/201/5">
         <ns2:Employee>
            <ns2:MessageList>
               <ns2:Message>
                  <ns4:Type xmlns:ns4="http:test/201/9">new</ns4:Type>
                  <ns4:Code xmlns:ns4="http:test/201/9">1</ns4:Code>
                  <ns4:Source xmlns:ns4="http:test/201/9">contract</ns4:Source>
                  <ns4:Description xmlns:ns4="http:test/201/9">new hire</ns4:Description>
               </ns2:Message>
            </ns2:MessageList>
         </ns2:Employee>
      </ns2:ResponseData>
   </Body>
</Envelope>

在语义上与之前的结果相同。

【讨论】:

  • 谢谢。这真的很有帮助。我对输入做了小改动。期望相同的输出:
  • 回答了我最初的问题。我对输入进行了小改动,等待答案。
  • @Mike 我没有看到任何变化。无论如何,如果是很小的变化,您应该可以自己进行调整。否则发布一个新问题。
  • 迈克尔现在怎么样?
  • 以同样的方式,如果我在输入中有默认命名空间属性 ex : xmlns:"example.com"。如何复制除此之外的所有内容?
猜你喜欢
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-12-31
  • 1970-01-01
  • 2010-09-09
  • 2023-03-24
  • 2012-08-24
  • 2012-07-29
相关资源
最近更新 更多