2011-03-03 27 views
1

輸入是mutliRef編碼的SOAP消息/文檔。如何使用 XSLT來平整multiRefs。 Multiref節點可以多次引用使用 ,並且它們本身遞歸地引用其他multiRef節點。創建XSLT變換以扁平化multiRef編碼的SOAP消息

結構中唯一可以引用的部分是 multiRef元素和@id和@href屬性。其他元素或 名稱空間可能會更改。

樣品輸入的信息是:

<?xml version="1.0" encoding="utf-8"?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
    <ns1:getAccountDTOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:ns1="http://www.example.com/pw/services/PWServices"> 
     <getAccountDTOReturn href="#id0" /> 
    </ns1:getAccountDTOResponse> 
    <multiRef id="id0" soapenc:root="0" 
    soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
    xsi:type="ns2:Account" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:ns2="urn:PWServices"> 
     <ID href="#id1" /> 
     <accountNumber xsi:type="soapenc:string"></accountNumber> 
     <accountType xsi:type="soapenc:string"></accountType> 
     <clientData xsi:type="soapenc:Array" xsi:nil="true" /> 
     <name xsi:type="soapenc:string"></name> 
     <parentRef xsi:type="soapenc:string"></parentRef> 
    </multiRef> 
    <multiRef id="id1" soapenc:root="0" 
    soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
    xsi:type="xsd:long" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> 
    0</multiRef> 
    </soapenv:Body> 
</soapenv:Envelope> 

預期成果是:

<?xml version="1.0"?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
    <ns1:getAccountDTOResponse xmlns:ns1="http://www.example.com/pw/services/PWServices" 
    soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 

     <getAccountDTOReturn xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
     xmlns:ns2="urn:PWServices" 
     soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
     xsi:type="ns2:Account"> 
     <ns1:ID soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
     xsi:type="xsd:long">0</ns1:ID> 
     <ns1:accountNumber xsi:type="soapenc:string" /> 
     <ns1:accountType xsi:type="soapenc:string" /> 
     <ns1:clientData xsi:type="soapenc:Array" xsi:nil="true" /> 
     <ns1:name xsi:type="soapenc:string" /> 
     <ns1:parentRef xsi:type="soapenc:string" /> 
     </getAccountDTOReturn> 
    </ns1:getAccountDTOResponse> 
    </soapenv:Body> 
</soapenv:Envelope> 

更新: 在上面的例子中,從邏輯上講,應該怎樣發生的是:

在第一遍,getAccountDTOResponse包含@href =「#id0」,以便將元素替換爲所有的子元素multiRef el與@ id =「id0」一起除外。

在第二遍中,應該發現@href =「#id1」,ID元素應該用@ id =「id1」替換爲元素的內容。

輸出中不應存在multiRef元素。如果參與整個multiRef混亂,則輸出中不應存在@id或@href屬性。

+0

現在還不是很清楚究竟應該進入什麼。請問,請將此添加到您的問題中? – 2011-03-03 19:33:31

+0

@Dimitre我在問題的底部添加了一些說明。 – 2011-03-03 21:54:48

回答

7

亞歷克斯,我沒有完全匹配你的輸出,但這裏是你如何通過hrefs來解析你的文檔。

這個樣式表:

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" > 

    <xsl:key name="multiref-by-id" match="multiRef" use="@id"/> 

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

    <xsl:template match="*[starts-with(@href, '#')]"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | 
      key('multiref-by-id', substring-after(@href, '#'))/@* | 
      key('multiref-by-id', substring-after(@href, '#'))/node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="@href[starts-with(., '#')] | multiRef[@id] | @soapenc:root"/> 

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

鑑於此輸入:

<?xml version="1.0" encoding="utf-8"?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
     <ns1:getAccountDTOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
            xmlns:ns1="http://www.example.com/pw/services/PWServices"> 
      <getAccountDTOReturn href="#id0"/> 
     </ns1:getAccountDTOResponse> 
     <multiRef id="id0" soapenc:root="0" 
        soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
        xsi:type="ns2:Account" 
        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
        xmlns:ns2="urn:PWServices"> 
      <ID href="#id1"/> 
      <accountNumber xsi:type="soapenc:string"></accountNumber> 
      <accountType xsi:type="soapenc:string"></accountType> 
      <clientData xsi:type="soapenc:Array" xsi:nil="true"/> 
      <name xsi:type="soapenc:string"></name> 
      <parentRef xsi:type="soapenc:string"></parentRef> 
     </multiRef> 
     <multiRef id="id1" soapenc:root="0" 
        soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
        xsi:type="xsd:long" 
        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> 
      0 
     </multiRef> 
    </soapenv:Body> 
</soapenv:Envelope> 

產生以下結果:

<?xml version="1.0" encoding="UTF-8"?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
     <ns1:getAccountDTOResponse xmlns:ns1="http://www.example.com/pw/services/PWServices" 
            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
      <getAccountDTOReturn id="id0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
           xsi:type="ns2:Account"> 
       <ID xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" id="id1" 
        soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:long"> 
        0 
       </ID> 
       <accountNumber xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" 
           xsi:type="soapenc:string"/> 
       <accountType xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" 
          xsi:type="soapenc:string"/> 
       <clientData xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" 
          xsi:type="soapenc:Array" xsi:nil="true"/> 
       <name xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" 
         xsi:type="soapenc:string"/> 
       <parentRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" 
          xsi:type="soapenc:string"/> 
      </getAccountDTOReturn> 
     </ns1:getAccountDTOResponse> 


    </soapenv:Body> 
</soapenv:Envelope> 

我認爲這apporach可以很容易地定製,以滿足您的需求。我想概述一下,提供的樣式表在@hrefs上運行,並沒有考慮任何元素名稱。因此可以靈活地使用它,而不必關注引用元素名稱。然而,所有的參考文獻應該被命名爲multiRef,但是這也可以很容易地定製。

+0

認爲這是正確的。認爲其中一個區別不是從輸出中刪除@id屬性,另一個是我的示例輸出引用了ns1命名空間,不知道從哪裏輸入。這可能是該函數的命令版本中的一個錯誤。 – 2011-03-04 05:24:20

0

這個樣式表:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> 
    <xsl:key name="kMultiRefById" match="multiRef" use="@id"/> 
    <xsl:output method="xml"/> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="getAccountDTOReturn"> 
     <xsl:variable name="vRefer" 
         select="key('kMultiRefById',substring(@href,2))"/> 
     <xsl:copy> 
      <xsl:copy-of select="$vRefer/namespace::*"/> 
      <xsl:apply-templates select="$vRefer/@*|$vRefer/node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="multiRef|multiRef/@id|multiRef/@soapenc:root"/> 
</xsl:stylesheet> 

輸出:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
     <ns1:getAccountDTOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
            xmlns:ns1="http://www.example.com/pw/services/PWServices"> 
      <getAccountDTOReturn soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
           xsi:type="ns2:Account" 
           xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
           xmlns:ns2="urn:PWServices"> 
       <ID href="#id1"></ID> 
       <accountNumber xsi:type="soapenc:string"></accountNumber> 
       <accountType xsi:type="soapenc:string"></accountType> 
       <clientData xsi:type="soapenc:Array" xsi:nil="true"></clientData> 
       <name xsi:type="soapenc:string"></name> 
       <parentRef xsi:type="soapenc:string"></parentRef> 
      </getAccountDTOReturn> 
     </ns1:getAccountDTOResponse> 
    </soapenv:Body> 
</soapenv:Envelope> 

注意:鍵交叉引用。身份規則。空的剝離規則。 雖然我只知道Mozilla的TransforMiiX,但它沒有實現namespaces::軸,但是對於每個XSLT處理器,複製名稱空間節點可能不是可行的。

+0

這很接近,但並不完整。在ID元素中,href =「#id1」未解析。此外,無法緩解getAccountDTOReturn,因爲它會改變,我認爲匹配將不得不基於@href現有。 – 2011-03-03 22:01:53