2013-05-01 20 views
1

我有一個我想用來過濾所提供的xml文件的id列表。應該保留列表中的每個節點,並且不在列表中的每個節點都被刪除。XSLT刪除不在列表中的節點,同時保留列表中的任何子節點

對我來說,困難是當我刪除一個節點(不在IDList中)時,我最終還會刪除一個可能在IDList中的子節點。

最後,我需要保持節點的嵌套(參見下面的示例)。

這是我的ID列表:

= IDList表2,3,5,6

這是我的輸入XML是:

<Associations> 
    <Association ASSOCIATION_ID="1"> 
     Elmwood Association 
     <Homes/> 
    </Association> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="4"> 
      Oakwood Sub Association A 
      <Homes/> 
      <Association ASSOCIATION_ID="6"> 
       Oakwood Sub Sub Association 
       <Homes/> 
      </Association> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

這是我的期望輸出:

<Associations> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="6"> 
      Oakwood Sub Sub Association 
      <Homes/> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

任何幫助將不勝感激!

回答

0

I. XSLT 2.0溶液:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="pIds" select="2, 3, 5, 6" as="xs:integer+"/> 

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

<xsl:template priority="2" match= 
    "Association[not(@ASSOCIATION_ID = $pIds) 
      and not(.//Association[@ASSOCIATION_ID = $pIds])]"/> 

<xsl:template match= 
    "Association[@ASSOCIATION_ID = $pIds] 
     //Association[not(@ASSOCIATION_ID = $pIds)] 
    | 
    *[not(self::Association[@ASSOCIATION_ID = $pIds])] 
     /node()[not(descendant-or-self::Association[@ASSOCIATION_ID = $pIds])] 
    "> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<Associations> 
    <Association ASSOCIATION_ID="1"> 
     Elmwood Association 
     <Homes/> 
    </Association> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="4"> 
      Oakwood Sub Association A 
      <Homes/> 
      <Association ASSOCIATION_ID="6"> 
       Oakwood Sub Sub Association 
       <Homes/> 
      </Association> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

產生想要的,正確的結果

<Associations> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="6"> 
       Oakwood Sub Sub Association 
       <Homes/> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

二, XSLT 1.0解決方案:

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

<my:ids> 
    <id>2</id> 
    <id>3</id> 
    <id>5</id> 
    <id>6</id> 
</my:ids> 

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

<xsl:template priority="2" match= 
    "Association[not(@ASSOCIATION_ID = document('')/*/my:ids/*) 
      and not(.//Association[@ASSOCIATION_ID = document('')/*/my:ids/*])]"/> 

<xsl:template match= 
    "Association[@ASSOCIATION_ID = document('')/*/my:ids/*] 
     //Association[not(@ASSOCIATION_ID = document('')/*/my:ids/*)] 
    | 
    *[not(self::Association[@ASSOCIATION_ID = document('')/*/my:ids/*])] 
     /node()[not(descendant-or-self::Association 
         [@ASSOCIATION_ID = document('')/*/my:ids/*])] 
    "> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 
+0

Dimitre,我是不正確的指定XSLT的2.0,所以XSLT的1.0是唯一可用的選項(對不起!)。當我嘗試你的代碼時,我只返回與association_Id = 2節點的關聯。這是因爲我在xslt-1.0? – Schletz 2013-05-02 12:39:12

+0

@ user2340911,如果您的XSLT 1.0處理器是真正兼容的並且不是bug,則應該收到編譯時錯誤消息或至少發出警告。至於將其轉換爲XSLT 1.0,這是可能的,但看起來更笨拙。我現在要開始工作 - 從現在開始大約10個小時之後,我們將能夠看看XSLT 1.0解決方案。 – 2013-05-02 14:32:23

+0

@Schletz,我根據要求向此答案添加了XSLT 1.0解決方案。 – 2013-05-03 03:11:27