2013-02-18 106 views
2

我已經審查了幾個單獨做這些事情的職位,但還沒有成功將它們組合在一起。複製XML,同時排除父節點,刪除特定的子節點並覆蓋一些子節點

我也有類似的這種結構的輸入:

<Response> 
    <Confirmation>Success</Confirmation> 
    <SecondResponse> 
     <InquiryResponse> 
      <ID>99999</ID> 
      <Confirmation>Success</Confirmation> 
      <Exception/> 
      <!-- The following structure repeats a varying amount of times --> 
      <DataNode1> 
      <!-- Child nodes could be null, transform should remove null nodes --> 
      <Child1>data</Child1> 
      ... 
      <Childn>dataN</Childn> 
      </DataNode1> 
      ... 
      <DataNodeN> 
      <Child1>data</Child1> 
      ... 
      <Childn>dataN</Childn> 
      </DataNodeN> 
     </InquiryResponse> 
    </SecondResponse> 
</Response> 

現在,我需要做到以下幾點:

1)複製的<InquiryResponse>所有子節點(但不是<InquiryResponse>本身)

2)排除<Confirmation><Exception>節點

3)排除任何空chi ldren在數據管理部

4)在數據管理部插入一個新的子元素

因此所需的輸出應該是這樣的:

<ID>99999</ID> 
<DataNode1> 
    <Child1>data</Child1> 
    <ChiildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNode1> 
... 
<DataNodeN> 
    <Child1>data</Child1> 
    <ChildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNodeN> 

我相信我有做到這一點通過創建一個模板每個DataNode(我知道所有可能發生的值)以及用於刪除不需要的節點的模板,然後將它們全部應用於忽略空節點的主副本模板。這是我目前的XSLT的化身,採用2.0 - 雖然我知道這並不完全是完整的,這是據我已經得到了:

<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    <!-- Remove Unwanted Nodes --> 
    <xsl:template match='Confirmation|Exception'/> 

    <!-- DataNode Template --> 
    <template match='DataNode1'> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <ChildInsert> 
      <xsl:value-of select='newData'/> 
     </ChildInsert> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Identity Transform --> 
    <xsl:template match='@*|node()'> 
    <xsl:if test='. != ""'> 
     <xsl:copy> 
     <xsl:apply-templates select='@*|node()'/> 
     </xsl:copy> 
    </xsl:if> 
    </xsl:template> 

    </xsl:stylesheet> 

這是我使用撒克遜-PE 9.3產生輸出.0.5

<Response> 
    <SecondResponse> 
    <InquiryResponse> 
     <ID>99999</ID> 
     <DataNode1> 
      <Child1>data</Child1> 
      <ChiildInsert>newData</ChildInsert> 
      <Childn>dataN</Childn> 
     </DataNode1> 
     .... 
     <DataNodeN>...</DataNodeN> 
    </InquiryResponse> 
    </SecondResponse> 
</Response> 

很明顯,我仍然得到所有的迴應父母,因爲我沒有指定一種方法來處理它們;但是,每當我嘗試將模板匹配到XPath時,我都會獲取數據,而不是XML。我知道我可以通過另一個轉換,只是複製<InquiryResponse>的子節點,但我覺得應該有更優雅的方式來做到這一點。以下是我仍然面臨的問題/問題。 1)由於使用這樣的模板:<xsl:template match='Response'/>會使我的整個響應爲空,我嘗試切換識別模板以匹配Response/SecondResponse/InquiryResponse/*,但結果只產生文本數據而不是XML。

2)當<Exception>節點填充值時,它將繼續被複制而不是像<Confirmation>節點那樣被刪除。 3)如果我想更新一個非空的子節點的值,我會這樣做嗎?還有一個額外的要求是更新一些兒童節點,所以我仍然在考慮如何去做,而這看起來是正確的方法,但我想驗證一下。

<xsl:template match='childNodeA'> 
    <childNodeA> 
     <xsl:value-of select='someValue/> 
    </childNodeA> 
</xsl:template> 

我道歉,如果這還不清楚,但隨時要求你做任何需要的進一步的細節和巨大的預先感謝您的人誰可以幫助。

回答

8

您發佈的輸出XML格式不正確,因爲它沒有根元素,但是這個XSLT 1。0樣式表應該做你想要什麼:

樣式

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

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

    <!-- Apply all child nodes; don't copy the element itself --> 
    <xsl:template match="Response | SecondResponse | InquiryResponse"> 
    <xsl:apply-templates/> 
    </xsl:template> 

    <!-- Drop elements --> 
    <xsl:template match="Confirmation | Exception"/> 

    <xsl:template match="DataNode1 | DataNode2 | DataNodeN"> 
    <xsl:copy> 
     <!-- Apply Child1, ignore children with no text content --> 
     <xsl:apply-templates select="Child1[normalize-space(.)]"/> 
     <!-- Insert new element --> 
     <ChildInsert>newData</ChildInsert> 
     <!-- Apply all other child elements except Child1 --> 
     <xsl:apply-templates select="*[normalize-space(.)][not(self::Child1)]"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

輸入

<Response> 
    <Confirmation>Success</Confirmation> 
    <SecondResponse> 
    <InquiryResponse> 
     <ID>99999</ID> 
     <Confirmation>Success</Confirmation> 
     <Exception/> 
     <!-- The following structure repeats a varying amount of times --> 
     <DataNode1> 
      <!-- Child nodes could be null, transform should remove null nodes --> 
      <Child1>data</Child1> 
      <Childn>dataN</Childn> 
     </DataNode1> 
     <DataNodeN> 
      <Child1>data</Child1> 
      <Childn>dataN</Childn> 
     </DataNodeN> 
    </InquiryResponse> 
    </SecondResponse> 
</Response> 

輸出

<?xml version="1.0" encoding="utf-8"?> 
<ID>99999</ID> 
<DataNode1> 
    <Child1>data</Child1> 
    <ChildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNode1> 
<DataNodeN> 
    <Child1>data</Child1> 
    <ChildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNodeN> 

請注意,由於您沒有指定「null」的含義,因此我假設它指的是沒有文本內容的元素。因此,上面的代碼將像這樣刪除<Child1>元素:

<Child1> 
    <GrandChild1/> 
</Child1> 
+0

正確,「空白」節點應該是沒有文本的節點。即。感謝您的回覆,我會盡快進行測試! – 2013-02-18 17:16:56

+0

這幾乎是完美的。我仍然得到SecondResponse和查詢響應節點,並且我仍然遇到如果Exception節點具有文​​本,它仍然被複制的問題。任何想法是如何我可能無法拍攝這些物品?再次感謝! – 2013-02-19 22:03:29

+0

您是否使用了我粘貼的確切的XSLT樣式表和輸入文檔?因爲如果你是,如果你仍然遇到這些問題,我會感到非常驚訝。我嘗試過使用'xsltproc'和Saxon 9.1.0.5J,它可以像兩個處理器一樣按預期工作。另一方面,如果你的樣式表或輸入文檔不同,我將無法看到它們。順便說一句,我無法用原始樣式表重現'Exception'節點的問題。 – 2013-02-19 22:17:44