2017-07-31 50 views
0

我有一個關於將多個節點合併到一個節點的問題。但我無法弄清楚如何做到這一點。將多個字段合併爲一個使用xslt

我有下面的XML文件:

<soap:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
       xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
       xmlns:s1="http://microsoft.com/wsdl/types/" 
       xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
       xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"> 
    <soap:Body> 
     <RetrieveTicketUpdatesResponse> 
      <RetrieveTicketUpdatesResult> 
       <TicketUpdates> 
        <TicketUpdate> 
         <FreeFields> 
          <FreeField> 
           <FreeFieldID>9876</FreeFieldID> 
           <Value>Yes</Value> 
          </FreeField> 
         </FreeFields> 
         <FreeFields> 
          <FreeField> 
           <FreeFieldID>8765</FreeFieldID> 
           <Value>Fiber</Value> 
          </FreeField> 
         </FreeFields> 
         <Id>1234</ticketId> 
         <Status>New</status> 
        </TicketUpdate> 
        <TicketUpdate> 
         <TicketUpdate> 
         <FreeFields> 
          <FreeField> 
           <FreeFieldID>6823</FreeFieldID> 
           <Value>No</Value> 
          </FreeField> 
         </FreeFields> 
         <FreeFields> 
          <FreeField> 
           <FreeFieldID>3453</FreeFieldID> 
           <Value>Fiber</Value> 
          </FreeField> 
         </FreeFields> 
         <Id>2343</ticketId> 
         <Status>Update</status> 
        </TicketUpdate> 
       </TicketUpdates> 
      </RetrieveTicketUpdatesResult> 
     </RetrieveTicketUpdatesResponse> 
    </soap:Body> 
</soap:Envelope> 

而且我想給FreeFields節點合併成1個節點像下面並創建以下的輸出:

<soap:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
       xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
       xmlns:s1="http://microsoft.com/wsdl/types/" 
       xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
       xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"> 
    <soap:Body> 
     <RetrieveTicketUpdatesResponse> 
      <RetrieveTicketUpdatesResult> 
       <TicketUpdates> 
        <TicketUpdate> 
         <FreeFields> 
          <FreeField> 
           <FreeFieldID>9876</FreeFieldID> 
           <Value>Yes</Value> 
          </FreeField> 
          <FreeField> 
           <FreeFieldID>8765</FreeFieldID> 
           <Value>Fiber</Value> 
          </FreeField> 
          <FreeField> 
           <FreeFieldID>7654</FreeFieldID> 
           <Value>https://www.stackoverflow.com</Value> 
          </FreeField> 
         </FreeFields> 
         <Id>1234</ticketId> 
         <Status>New</status> 
        </TicketUpdate> 
        <TicketUpdate> 
         <TicketUpdate> 
         <FreeFields> 
          <FreeField> 
           <FreeFieldID>6823</FreeFieldID> 
           <Value>No</Value> 
          </FreeField> 
          <FreeField> 
           <FreeFieldID>3453</FreeFieldID> 
           <Value>Fiber</Value> 
          </FreeField> 
          <FreeField> 
           <FreeFieldID>8563</FreeFieldID> 
           <Value>https://www.stackexchange.com</Value> 
          </FreeField> 
         </FreeFields> 
         <Id>2343</ticketId> 
         <Status>Update</status> 
        </TicketUpdate> 
       </TicketUpdates> 
      </RetrieveTicketUpdatesResult> 
     </RetrieveTicketUpdatesResponse> 
    </soap:Body> 
</soap:Envelope> 

我試圖用一個xsl:for-each。並將其複製到一個新的列表中,但我無法弄清楚如何完成此操作。 有人能幫我一個例子嗎? 我試着用Google搜索解決方案,但無法找到解決方案。

更新1 這是我使用

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" version="1.0"> 

    <xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes" /> 

    <!-- Stylesheet to inject namespaces into a document in specific places --> 
    <xsl:template match="/"> 
    <soap:Envelope> 
     <soap:Body> 
     <RetrieveTicketUpdatesResponse> 

      <xsl:choose> 
      <!-- Handle 'Root' wrapper added by JSON to XML policy --> 
      <xsl:when test="normalize-space(/Root)"> 
       <RetrieveTicketUpdatesResult> 
       <xsl:apply-templates select="node()|@*" /> 
       </RetrieveTicketUpdatesResult> 
      </xsl:when> 

      <!-- If the root element is not what was in the schema, add it --> 
      <xsl:when test="not(normalize-space(/RetrieveTicketUpdates))"> 
       <RetrieveTicketUpdatesResult> 
       <xsl:apply-templates select="node()|@*" /> 
       </RetrieveTicketUpdatesResult> 
      </xsl:when> 
      <!-- everything checks out, just copy the xml--> 
      <xsl:otherwise> 
       <xsl:apply-templates select="node()|@*" /> 
      </xsl:otherwise> 
      </xsl:choose> 
     </RetrieveTicketUpdatesResponse> 
     </soap:Body> 
    </soap:Envelope> 
    </xsl:template> 

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

    <xsl:template match="/FreeFields/*/FreeField" name="copy-freefields"> 
    <xsl:element name="{local-name()}"> 
     <xsl:copy-of select="*" /> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="/Root/*" name="copy-root"> 
    <xsl:element name="{local-name()}"> 
     <xsl:copy-of select="namespace::*" /> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="*[not(local-name()='Root') and not(local-name()='Array')]" name="copy-all"> 
    <xsl:element name="{local-name()}"> 
     <xsl:copy-of select="namespace::*" /> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:element> 
    </xsl:template> 

    <!-- template to copy the rest of the nodes --> 
    <xsl:template match="comment() | processing-instruction()"> 
    <xsl:copy /> 
    </xsl:template> 
</xsl:stylesheet> 
+0

請發佈您的嘗試,以便我們可以修復它,而不必從頭爲您編寫代碼。同時說明如果使用XSLT 1.0或2.0。 –

+0

另請注意,您向我們顯示的輸入和輸出都缺少一個將'soap'前綴綁定到名稱空間URI的名稱空間聲明。 –

回答

1

試試下面的腳本XSLT:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:soap="http://schemas.xmlsoap.org/soap"> 
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="TicketUpdate"> 
    <xsl:copy> 
     <FreeFields> 
     <xsl:copy-of select="FreeFields/FreeField"/> 
     </FreeFields> 
     <xsl:apply-templates select="*[name() != 'FreeFields']"/> 
    </xsl:copy> 
    </xsl:template> 

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

你也糾正源XML一些錯誤。

+0

Tnx! :)我的源代碼XML更大,剝離了許多額外的節點。我想我沒有正確編輯它。你的解決方案就像一個魅力 – MFasseur