2013-06-21 38 views
1

我是XSLT新手,面臨修改xml的問題。如何從考慮參數值的XML文件中刪除重複元素

的輸入XML是:

<?xml version="1.0" encoding="UTF-8"?> 
<xml> 

    <dictionary> 
     <label>A</label> 
     <brand>top</brand> 
     <color>black</color> 
    </dictionary> 

    <dictionary> 
     <label>B</label> 
     <brand>lower</brand> 
     <color>brown</color> 
    </dictionary> 

    <dictionary> 
     <label>A</label> 
     <brand>lower</brand> 
     <color>yello</color> 
    </dictionary> 

    <dictionary> 
     <label>C</label> 
     <brand>middle</brand> 
     <color>orange</color> 
    </dictionary> 

    <dictionary> 
     <label>B</label> 
     <brand>top</brand> 
     <color>blue</color> 
    </dictionary> 

    <dictionary> 
     <label>D</label> 
     <brand>mid</brand> 
     <color>green</color> 
    </dictionary> 

    <dictionary> 
     <label>A</label> 
     <brand>mid</brand> 
     <color>yello</color> 
    </dictionary> 

</xml> 

它包含一些具有子元素的A作爲一個元件。我想刪除包含重複項的字典節點。 !此外,雖然它消除了重複,它應該只刪除其中也包含了重複的節點=低

的預期結果是:

<?xml version="1.0" encoding="UTF-8"?> 
<xml> 

    <dictionary> 
     <label>B</label> 
     <brand>lower</brand> 
     <color>brown</color> 
    </dictionary> 

    <dictionary> 
     <label>A</label> 
     <brand>lower</brand> 
     <color>yello</color> 
    </dictionary> 

    <dictionary> 
     <label>C</label> 
     <brand>middle</brand> 
     <color>orange</color> 
    </dictionary> 

    <dictionary> 
     <label>D</label> 
     <brand>mid</brand> 
     <color>green</color> 
    </dictionary> 

</xml> 

在互聯網上,我發現了一個XSL來刪除重複的節點基於元素值。刪除重複的節點的XSL是:

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

<xsl:key name="LABEL" match="dictionary" use="label"/> 

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

<xsl:template match="dictionary[not(generate-id() = generate-id(key('LABEL', label)[1]))]" /> 
</xsl:stylesheet> 

回答

0

你的描述「!而它消除了重複,它應該只刪除其中也包含=低重複節點」是我也不清楚,我試圖實現它然而用XSLT 2.0如下:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output indent="yes"/> 

<xsl:template match="xml"> 
    <xsl:copy> 
    <xsl:for-each-group select="dictionary" group-by="label"> 
     <xsl:copy-of select="if (count(current-group()) eq 1) 
          then . 
          else current-group()[contains(brand, 'lower')]"/> 
    </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

,其將所述輸入

<?xml version="1.0" encoding="UTF-8"?> 
<xml> 

    <dictionary> 
     <label>A</label> 
     <brand>top</brand> 
     <color>black</color> 
    </dictionary> 

    <dictionary> 
     <label>B</label> 
     <brand>lower</brand> 
     <color>brown</color> 
    </dictionary> 

    <dictionary> 
     <label>A</label> 
     <brand>lower</brand> 
     <color>yello</color> 
    </dictionary> 

    <dictionary> 
     <label>C</label> 
     <brand>middle</brand> 
     <color>orange</color> 
    </dictionary> 

    <dictionary> 
     <label>B</label> 
     <brand>top</brand> 
     <color>blue</color> 
    </dictionary> 

    <dictionary> 
     <label>D</label> 
     <brand>mid</brand> 
     <color>green</color> 
    </dictionary> 

    <dictionary> 
     <label>A</label> 
     <brand>mid</brand> 
     <color>yello</color> 
    </dictionary> 

</xml> 

到以下結果:

<xml> 
    <dictionary> 
     <label>A</label> 
     <brand>lower</brand> 
     <color>yello</color> 
    </dictionary> 
    <dictionary> 
     <label>B</label> 
     <brand>lower</brand> 
     <color>brown</color> 
    </dictionary> 
    <dictionary> 
     <label>C</label> 
     <brand>middle</brand> 
     <color>orange</color> 
    </dictionary> 
    <dictionary> 
     <label>D</label> 
     <brand>mid</brand> 
     <color>green</color> 
    </dictionary> 
</xml> 

樣式表基團上的label子元素值dictionary元件和爲每個組輸出任一組中的單個元件,如果是隻有一種或它輸出其中brand子元素值確實在組中的那些元件包含lower

作爲評論的要求,我添加使用Muenchian grouping代替for-each-group的XSLT 1.0樣式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="by-label" match="dictionary" use="label"/> 

<xsl:template match="xml"> 
    <xsl:copy> 
    <xsl:for-each select="dictionary[generate-id() = generate-id(key('by-label', label)[1])]"> 
     <xsl:variable name="current-group" select="key('by-label', label)"/> 
     <xsl:choose> 
     <xsl:when test="count($current-group) = 1"> 
      <xsl:copy-of select="."/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy-of select="$current-group[brand = 'lower']"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

感謝馬丁。這實際上意味着品牌!=更低,我認爲你正確解釋併產生了所需的輸出。我們可以在xsl 1.0中編寫相同的xsl登錄,因爲我在代碼中的所有地方都使用了1.0。如果我可以在xsl 1.0中得到相同的結果,這將非常有幫助。 – Ravi

+0

我將編輯並顯示XSLT 2.0代碼到XSLT 1.0的轉錄。 –

+0

非常感謝馬丁。這符合預期。 – Ravi