2011-09-17 84 views
2

我有以下XML。我必須在肥皂包裹下包括肥皂身體。XSLT - 複製多個名稱空間

<headers> 
    <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:def="http://lmn" xmlns:abc="http://xyz"><soapenv:Header><abc:Security> <abc:UsernameToken> 
    <abc:Username>abc</abc:Username> 
         <abc:Password>pwd</abc:Password> 
        </abc:UsernameToken> 
      </abc:Security> 
     </soapenv:Header> 
    </soapenv:Envelope> 
</headers> 

我的輸出應該像

 <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:def="http://lmn" xmlns:abc="http://xyz"> 
     <soapenv:Header> 
      <abc:Security> 
        <abc:UsernameToken> 
         <abc:Username>abc</abc:Username> 
         <abc:Password>pwd</abc:Password> 
        </abc:UsernameToken> 
      </abc:Security> 
     </soapenv:Header> 
     <soapenv:Body><a><b></b><c></c></a></soapenv:Body> 
    </soapenv:Envelope> 

以下是我的XSL。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:soap="http://www.w3.org/2003/05/soap-envelope" exclude-result-prefixes="xd soap soapenv"> 
<xsl:template match="/"> 
     <xsl:variable name="envNode"><xsl:copy-of select="name(headers/*)"/></xsl:variable> 
     <xsl:choose> 
      <xsl:when test="contains($envNode,'soapenv')"> 
       <xsl:element name="{name(headers/*)}">     
        <xsl:copy-of select="headers/soapenv:Envelope/*"/> 
        <xsl:element name="soapenv:Body"> 
         <a><b></b><c></c></a> 
        </xsl:element> 
       </xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:element name="{name(soapOptions/headers/*)}">     
      <xsl:copy-of select="soapOptions/headers/soap:Envelope/*"/> 
      <xsl:element name="soap:Body"> 
       <a><b></b><c></c></a> 
      </xsl:element> 
      </xsl:element> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

我收到以下輸出。

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> 
    <soapenv:Header xmlns:def="http://lmn" xmlns:abc="http://xyz""> 
      <abc:Security> 
        <abc:UsernameToken> 
         <abc:Username>abc</abc:Username> 
         <abc:Password>pwd</abc:Password> 
        </abc:UsernameToken> 
      </abc:Security> 
     </soapenv:Header> 
     <soapenv:Body><a><b/><c/></a></soapenv:Body> 
</soapenv:Envelope> 

我想複製soapenv中的所有名稱空間:Envelope節點到同一個節點。但它被複制到soapenv:Header。 我在XSL的元素名稱中嘗試了許多選項命名空間選項以及命名空間。 任何人都可以幫我解決這個問題。

由於提前, 納傑馬

+0

好問題+1這是瞭解最基本和最強大的XSLT設計模式的好機會 - 重寫身份規則,使用這種模式可以輕鬆解決問題,並且以簡化的標準方式解決諸如此類的許多問題,它要求基本上「按原樣」複製XML文檔,僅引入小的本地化修改。 –

回答

2

添加元素聲明下:

<xsl:copy-of select="headers/*/namespace::*"/> 

這將複製正確的元素想要的命名空間,從而防止XSLT處理器聲明它們在其他地方。


XSLT驗證:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> 

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
     <xsl:element name="{name(headers/*)}"> 
      <xsl:copy-of select="headers/*/namespace::*"/> 
      <xsl:copy-of select="headers/soapenv:Envelope/*"/> 
      <xsl:element name="soapenv:Body"> 
       <a><b></b><c></c></a> 
      </xsl:element> 
     </xsl:element> 

    </xsl:template> 

</xsl:stylesheet> 

生產:

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:def="http://lmn" xmlns:abc="http://xyz"> 
    <soapenv:Header> 
     <abc:Security> 
     <abc:UsernameToken> 
      <abc:Username>abc</abc:Username> 
      <abc:Password>pwd</abc:Password> 
     </abc:UsernameToken> 
     </abc:Security> 
    </soapenv:Header> 
    <soapenv:Body> 
     <a> 
     <b/> 
     <c/> 
     </a> 
    </soapenv:Body> 
</soapenv:Envelope> 

但是,如果你可以改變你的樣式表,我會用更簡單的東西,如:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> 

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="headers"> 
     <xsl:apply-templates select="node()"/> 
    </xsl:template> 

    <xsl:template match="soapenv:Header"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
      <soapenv:Body> 
       <a><b></b><c></c></a> 
      </soapenv:Body> 
    </xsl:template> 

</xsl:stylesheet> 
+1

謝謝。它的工作原理是:-) – Najma

+0

歡迎您。請確保** [接受答案](http:// meta.stackexchange.com/questions/5234/how-does-accepting-an-回答工作)**。 –

1

使用恐怕是最短的,最簡單,最標準化的解決方案

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

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

<xsl:template match="soapenv:Envelope"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    <soapenv:Body><a><b/><c/></a></soapenv:Body> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

當這種轉變是在所提供的XML文檔應用:

<headers> 
    <soapenv:Envelope 
     xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" 
     xmlns:def="http://lmn" xmlns:abc="http://xyz"> 
     <soapenv:Header> 
      <abc:Security> 
       <abc:UsernameToken> 
        <abc:Username>abc</abc:Username> 
        <abc:Password>pwd</abc:Password> 
       </abc:UsernameToken> 
      </abc:Security> 
     </soapenv:Header> 
    </soapenv:Envelope> 
</headers> 

想要的,正確的結果生產

<headers> 
    <soapenv:Envelope 
    xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" 
    xmlns:def="http://lmn" xmlns:abc="http://xyz"> 
     <soapenv:Header> 
     <abc:Security> 
      <abc:UsernameToken> 
       <abc:Username>abc</abc:Username> 
       <abc:Password>pwd</abc:Password> 
      </abc:UsernameToken> 
     </abc:Security> 
     </soapenv:Header> 
     <soapenv:Body> 
     <a> 
      <b/> 
      <c/> 
     </a> 
     </soapenv:Body> 
    </soapenv:Envelope> 
</headers> 

說明

  1. identity rule/template副本的每個節點 「原樣」

  2. 只有一個模板覆蓋了身份規則。它匹配soapenv:Envelope的處理是非常相似的標識模板(匹配的元素是「淺拷貝及其所有後代,它的身體內複製),但除此之外,新soapenv:Body也輸出。