2012-05-24 37 views
-5

輸入文件:如何使用XSLT根據節點屬性位置執行xml消除?

<root> 
    <sector> 
     <nodeA id="a"> 
      <section id="i"> 
       <item1 id="1" method="create"> 
        <somechild>a</somechild> 
       </item1> 

       <item1 id="1" method="delete" /> 
      </section>     
     </nodeA> 

     <nodeA id="b"> 
      <cell id="ii"> 
       <item2 id="2" method="create"> 
        <otherchild>a</otherchild> 
       </item2> 
      </cell> 
      <cell id="ii"> 
       <item2 id="2" method="delete" /> 
      </cell>     
     </nodeA> 

     <nodeB id="i"> 
      <cell id="ii"> 
       <item3 id="1" method="create"> 
        <child>b</child> 
       </item3> 
      </cell> 

      <cell id="ii"> 
       <item3 id="1" method="delete" /> 
       <item3 id="1" method="create"> 
        <otherchild>a</otherchild> 
       </item3> 
      </cell>     
     </nodeB> 
    </sector> 
</root> 

預期輸出:

<root> 
    <sector> 
     <nodeA id="a"> 
      <section id="i"> 
      </section>     
     </nodeA> 

     <nodeA id="b"> 
      <cell id="ii"> 
      </cell> 
      <cell id="ii"> 
      </cell>     
     </nodeA> 

     <nodeB id="i"> 
      <cell id="ii"> 
       <item3 id="1" method="create"> <!-- this is not eliminated as it violates the rule by having create followed by delete and followed by create again --> 
        <child>b</child> 
       </item3> 
      </cell> 

      <cell id="ii"> 
       <item3 id="1" method="delete" /> 
       <item3 id="1" method="create"> 
        <otherchild>a</otherchild> 
       </item3> 
      </cell>     
     </nodeB> 
    </sector> 
</root> 

我需要使用此規則,以消除XML節點:

  • 一個與method="create"節點,隨後用一個節點method="delete"將被淘汰
  • 該方案可以在一個父發生,或者在兩個上級,只要它具有相同的元素名稱和ID <cell id="ii">

我能如何使用XSLT 1.0或2.0的這種轉變蔓延?

謝謝。

+8

它可以是你一直在問同樣的問題,一遍又一遍,有效地讓SO用戶做你的工作?所有[你以前的問題](http://stackoverflow.com/users/1336019/john?tab=questions)外觀和感覺都一樣,但你不斷想出新的,就像其他人一樣。您已經收到了您的其他問題的長期完整答案,但我有這樣的感覺,即您只需複製代碼,忽略解釋並只需發佈另一個問題即可完成某些工作。對不起,這不是這個網站的工作原理。 – Tomalak

+0

@Tomalak如果你有這種感覺,我很抱歉。只是我正在執行這些案例來處理我的xml結構,因爲我無法在此發佈實際文件。這就是爲什麼我必須做一個比喻,當我把這些文件放在一起時,它不起作用,我必須改變這些問題,這些問題導致發佈類似的問題,但實際上有不同的算法。 – John

+1

在你的XSLT中,你有一條評論說'這不是因爲違反了規則,因爲它違反了創建,然後刪除,然後再次創建',但我看不出這與你在問題中指定的規則相關。你有'method =「create」'節點和'method =「delete」'節點,所以不應該被刪除?你能詳細說明這個規則嗎?謝謝! –

回答

1

這是一種方法。您可以定義一個鍵,將您要刪除的項目分組。我想你是元素的@id屬性與兩個父節點

<xsl:key 
    name="items" 
    match="*[@method != '']" use="concat(@id, '|', ../@id, '|', ../../@id)" /> 

接下來的@id屬性分組,在一起,你可以有一個模板來匹配您的@方法=「創建」那裏有在關鍵的兩個要素,以及其他項目的項目是一個@方法=「刪除」

<xsl:template match="* 
    [@method = 'create'] 
    [count(key('items', concat(@id, '|', ../@id, '|', ../../@id))) = 2] 
    [key('items', concat(@id, '|', ../@id, '|', ../../@id))[@method = 'delete']]" /> 

您還需要一個模板,在符合其他@方法=「刪除」類似的方式。

以下是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="items" match="*[@method != '']" use="concat(@id, '|', ../@id, '|', ../../@id)" /> 

    <xsl:template match="*[@method = 'create'][count(key('items', concat(@id, '|', ../@id, '|', ../../@id))) = 2][key('items', concat(@id, '|', ../@id, '|', ../../@id))[@method = 'delete']]" /> 
    <xsl:template match="*[@method = 'delete'][count(key('items', concat(@id, '|', ../@id, '|', ../../@id))) = 2][key('items', concat(@id, '|', ../@id, '|', ../../@id))[@method = 'create']]" /> 

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

當適用於您的示例XML,下面是輸出

<root> 
    <sector> 
     <nodeA id="a"> 
     <section id="i"/> 
     </nodeA> 
     <nodeA id="b"> 
     <cell id="ii"/> 
     <cell id="ii"/> 
     </nodeA> 
     <nodeB id="i"> 
     <cell id="ii"> 
      <item3 id="1" method="create"> 
       <child>b</child> 
      </item3> 
     </cell> 
     <cell id="ii"> 
      <item3 id="1" method="delete"/> 
      <item3 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item3> 
     </cell> 
     </nodeB> 
    </sector> 
</root>