2012-01-15 136 views
1

我有這樣的SOAP請求使用XSL更改命名空間URI:如何在SOAP請求

<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空間URI:docTypeRef_tns_sayHello元素別的東西(例如:http://test.fr) 。此命名空間定義可出現在 HEL:docTypeRef_tns_sayHello元件如在上面或在根Envelope元素的代碼,所以我想僅在Envelope元素

然後我想修改添加此命名空間定義mustUnderstand屬性的屬性值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> 

有人能幫助我嗎? 謝謝!

+1

可能重複[如何更改命名空間](http://stackoverflow.com/questions/6694908/how-to-change-namespace) – newtover 2012-01-15 14:07:41

+0

你是否只使用XSLT 1。0還是可以使用XSLT 2.0?我提供了一個XSLT 1.0解決方案,但是對於命名空間創建需求,需要在通用解決方案中使用擴展函數。在XSLT 2.0中不需要擴展功能。 – 2012-01-15 15:04:22

回答

0

一,這是一個通用的,參數化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指令從動態(靜態未知)部分動態構建新的名稱空間節點。

這裏是一個小例子,如何用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,並增加了一個新的命名空間節點,以它:

<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>