如何在soap请求中使用xsl更改命名空间uri [英] How to change namespace uri using xsl in soap request

查看:23
本文介绍了如何在soap请求中使用xsl更改命名空间uri的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个肥皂请求:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"         xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
    <wsse:Security mustUnderstand="1">
        <wsse:UsernameToken>
            <wsse:Username>test</wsse:Username>
            <wsse:Password>test</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>
<soapenv:Body>
  <hel:docTypeRef_tns_sayHello xmlns:hel="http://aaa/bbb.fr">
     <arg0>John</arg0>
     <arg1>111-222-333</arg1>
  </hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>

我想首先将出现在 hel:docTypeRef_tns_sayHello 元素中的命名空间 uri 更改为其他内容(例如:http://test.fr).这个命名空间定义可以出现在hel:docTypeRef_tns_sayHello 元素如上面的代码或在根 Envelope 元素中,所以我只想在 Envelope 元素中添加这个命名空间定义

I would like first to change the namespace uri appearing in the hel:docTypeRef_tns_sayHello element to something else (ex : http://test.fr). This namespace definition can appear in the hel:docTypeRef_tns_sayHello element as in the code above or in the root Envelope element, so i'd like to add this namespace definition only in the Envelope element

那我想把mustUnderstand属性的值修改为0.

Then I'd like to modify the value of mustUnderstand attribute to 0.

结果应该是这样的:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"       xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-    1.0.xsd" 
**xmlns:hel="http://test.fr"**>
<soapenv:Header>
    <wsse:Security mustUnderstand="**0**">
        <wsse:UsernameToken>
            <wsse:Username>test</wsse:Username>
            <wsse:Password>test</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>
<soapenv:Body>
  <hel:docTypeRef_tns_sayHello>
     <arg0>John</arg0>
     <arg1>111-222-333</arg1>
  </hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>

有人可以帮我吗?谢谢!

Could somebody help me ? Thancks !

推荐答案

I.这是一个通用的、参数化的 XSLT 1.0 解决方案:

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

 <xsl:param name="pElemName" select="'hel:docTypeRef_tns_sayHello'"/>
 <xsl:param name="pOldNamespace" select="'http://aaa/bbb.fr'"/>
 <xsl:param name="pNewNamespace" select="'http://test.fr'"/>

 <xsl:variable name="vPrefix" select="substring-before($pElemName, ':')"/>

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

 <xsl:template match="*">
  <xsl:choose>
      <xsl:when test=
       "not(name() = $pElemName
          and
            namespace-uri() = $pOldNamespace
           )
       ">
        <xsl:call-template name="identity"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="{name()}" namespace="{$pNewNamespace}">
         <xsl:copy-of select=
           "namespace::*
                 [not(name() = $vPrefix
                    and
                      . = $pOldNamespace
                      )
                ]"/>

         <xsl:apply-templates select="@*"/>

         <xsl:apply-templates select="node()" mode="removeNS"/>
        </xsl:element>
      </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="*" mode="removeNS">
  <xsl:choose>
   <xsl:when test=
     "not(starts-with(name(), $vPrefix)
        and
          namespace-uri() = $pOldNamespace
         )">
     <xsl:element name="{name()}" namespace="{namespace-uri()}">
         <xsl:copy-of select=
           "namespace::*
                 [not(name() = $vPrefix
                    and
                      . = $pOldNamespace
                      )
                ]"/>
       <xsl:apply-templates select="@*"/>
       <xsl:apply-templates select="node()" mode="removeNS"/>
     </xsl:element>
   </xsl:when>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="@mustUnderstand">
  <xsl:attribute name="{name()}">0</xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <soapenv:Header>
        <wsse:Security mustUnderstand="1">
            <wsse:UsernameToken>
                <wsse:Username>test</wsse:Username>
                <wsse:Password>test</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <hel:docTypeRef_tns_sayHello xmlns:hel="http://aaa/bbb.fr">
            <arg0>John</arg0>
            <arg1>111-222-333</arg1>
        </hel:docTypeRef_tns_sayHello>
    </soapenv:Body>
</soapenv:Envelope>

产生想要的、正确的结果:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
   <soapenv:Header>
      <wsse:Security mustUnderstand="0">
         <wsse:UsernameToken>
            <wsse:Username>test</wsse:Username>
            <wsse:Password>test</wsse:Password>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <hel:docTypeRef_tns_sayHello xmlns:hel="http://test.fr">
         <arg0>John</arg0>
         <arg1>111-222-333</arg1>
      </hel:docTypeRef_tns_sayHello>
   </soapenv:Body>
</soapenv:Envelope>

注意:在 XSLT 1.0 中,如果不使用扩展函数(至少 xxx:node-set())来动态添加新的命名空间是不可能的(它不作为命名空间节点存在)到一个元素.在 XSLT 2.0 中,新的 xsl:namespace 指令可用于从动态(静态未知)部分动态构造新的命名空间节点.

Do note: In XSLT 1.0 it isn't possible without using an extension function (at least xxx:node-set())to dynamically add a new namespace (that doesn't exist already as a namespace node) to an element. In XSLT 2.0 the new xsl:namespace instruction can be used to dynamically construct a new namespace node from dynamic (statically unknown) parts.

这里是一个小例子,如何使用 XSLT 1.0 在转换命名空间节点的开头添加一个新的、不存在的节点:

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

 <xsl:template match="/*">
  <xsl:variable name="vrtfDoc">
   <t xmlns:hel="http://test.fr"/>
  </xsl:variable>

  <xsl:variable name="vNS" select=
   "ext:node-set($vrtfDoc)/*/namespace::*
                               [name()='hel']"/>

  <xsl:element name="{name()}"
               namespace="{namespace-uri()}">
    <xsl:copy-of select="namespace::*"/>

    <xsl:copy-of select="$vNS"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

在此 XML 文档上应用此转换时:

<t xmlns:someNS="some:NS"/>

它使用其所有命名空间节点重新创建顶部元素 t 并向其添加一个新的命名空间节点:

it re-creates the top element t with all its namespace nodes and adds one new namespace node to it:

<t xmlns:someNS="some:NS" xmlns:hel="http://test.fr"/>

二.这是一个完整的 XSLT 2.0 解决方案:

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

 <xsl:param name="pElemName" select="'hel:docTypeRef_tns_sayHello'"/>
 <xsl:param name="pOldNamespace" select="'http://aaa/bbb.fr'"/>
 <xsl:param name="pNewNamespace" select="'http://test.fr'"/>

 <xsl:variable name="vPrefix" select="substring-before($pElemName, ':')"/>

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

 <xsl:template match="/*">
  <xsl:element name="{name()}" namespace="{namespace-uri()}">
   <xsl:namespace name="{$vPrefix}" select="$pNewNamespace"/>

   <xsl:copy-of select=
       "namespace::*
             [not(name() = $vPrefix
                and
                  . = $pOldNamespace
                  )
              ]"/>

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

 <xsl:template match="*">
  <xsl:choose>
      <xsl:when test=
       "not(name() = $pElemName
          and
            namespace-uri() = $pOldNamespace
           )
       ">
        <xsl:call-template name="identity"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="{name()}" namespace="{$pNewNamespace}">
         <xsl:copy-of select=
           "namespace::*
                 [not(name() = $vPrefix
                    and
                      . = $pOldNamespace
                      )
                ]"/>

         <xsl:apply-templates select="@*"/>

         <xsl:apply-templates select="node()" mode="removeNS"/>
        </xsl:element>
      </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="*" mode="removeNS">
  <xsl:choose>
   <xsl:when test=
     "not(starts-with(name(), $vPrefix)
        and
          namespace-uri() = $pOldNamespace
         )">
     <xsl:element name="{name()}" namespace="{namespace-uri()}">
         <xsl:copy-of select=
           "namespace::*
                 [not(name() = $vPrefix
                    and
                      . = $pOldNamespace
                      )
                ]"/>
       <xsl:apply-templates select="@*"/>
       <xsl:apply-templates select="node()" mode="removeNS"/>
     </xsl:element>
   </xsl:when>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="@mustUnderstand">
  <xsl:attribute name="{name()}">0</xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(上图)时,会产生所需的正确结果:

<soapenv:Envelope xmlns:hel="http://test.fr"
                  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
   <soapenv:Header>
      <wsse:Security mustUnderstand="0">
         <wsse:UsernameToken>
            <wsse:Username>test</wsse:Username>
            <wsse:Password>test</wsse:Password>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <hel:docTypeRef_tns_sayHello>
         <arg0>John</arg0>
         <arg1>111-222-333</arg1>
      </hel:docTypeRef_tns_sayHello>
   </soapenv:Body>
</soapenv:Envelope>

这篇关于如何在soap请求中使用xsl更改命名空间uri的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆