2012-03-09 75 views
1

我是xslt新手,並有一個尷尬的問題,我花了很多小時解決,但無法達成結論。預先感謝您的幫助。刪除重複的元素和收集與xslt一起的所有子節點

我有一個XML文件是這樣的:

<root> 

<ELEMENT id="1" > 

<CHILD name="aaa"> 
<EMPLOYEE>Mark</EMPLOYEE> 
<EMPLOYEE>John</EMPLOYEE> 
</CHILD> 

<CHILD name="bbb"> 
<EMPLOYEE>Tom</EMPLOYEE> 
</CHILD> 

</ELEMENT> 


<ELEMENT id="2" > 

<CHILD name="aaa"> 
<EMPLOYEE>leo</EMPLOYEE> 
<EMPLOYEE>Jason</EMPLOYEE> 
</CHILD> 


</ELEMENT> 

<ELEMENT id="1" > 

<CHILD name="aaa"> 
<EMPLOYEE>Tim</EMPLOYEE> 
</CHILD> 


</ELEMENT> 

</root> 

我嘗試做的是收集「員工」 S具有相同的「元素」標識和「孩子」的名字在一起,並刪除重複的「元」秒和「子」 S。

我的意思是我只需要一個人只有一個,但所有員工屬於id = 1 name = aaa。生成的文件應該如下所示:

<root> 
<ELEMENT id="1" > 

<CHILD name="aaa"> 
<EMPLOYEE>Mark</EMPLOYEE> 
<EMPLOYEE>John</EMPLOYEE> 
<EMPLOYEE>Tim</EMPLOYEE> 
</CHILD> 

<CHILD name="bbb"> 
<EMPLOYEE>Tom</EMPLOYEE> 
</CHILD> 

</ELEMENT> 


<ELEMENT id="2" > 

<CHILD name="aaa"> 
<EMPLOYEE>leo</EMPLOYEE> 
<EMPLOYEE>Jason</EMPLOYEE> 
</CHILD> 


</ELEMENT> 
</root> 

我的xslt代碼應該如何處理?我是否需要爲每個循環迭代一個循環,還是應該使用遞歸模板?

許多TNX


非常感謝您對您有用的答案。這遠遠超出我可以接觸到的程度。 但是,代碼刪除了一些不應刪除的CHILD節點。

我嘗試了一個更復雜的XML:

<ROOT> 
    <ELEMENT id="1" > 
    <CHILD name="aaa"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    <CHILD name="bbb"> 
     <EMPLOYEE> 
     adsf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="1" > 
    <CHILD name="aaa"> 
      <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    <CHILD name="ccc"> 
      <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="2" > 
    <CHILD name="ddd"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    <CHILD name="eee"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="3" > 
    <CHILD name="xxx"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    <CHILD name="yyy"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="4" > 
    <CHILD name="ddd"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 

    </CHILD> 
    <CHILD name="aaa"> 
     <EMPLOYEE> 
     adsf 
     </EMPLOYEE> 

    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="3" > 
    <CHILD name="xxx"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    <CHILD name="aaa"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="1" > 
    <CHILD name="aaa"> 
     <EMPLOYEE> 
    asdf 
     </EMPLOYEE> 

    </CHILD> 
    <CHILD name="bbb"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 
    <ELEMENT id="2" > 
    <CHILD name="ddd"> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 
     <EMPLOYEE> 
     asdf 
     </EMPLOYEE> 

    </CHILD> 
    <CHILD name="aaa"> 
     <EMPLOYEE> 
    asdf 
     </EMPLOYEE> 
    </CHILD> 
    </ELEMENT> 

</ROOT> 

回答

1

這種轉變

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

    <xsl:key name="kElemById" match="ELEMENT" use="@id"/> 
    <xsl:key name="kChildByNameAndParentId" 
     match="CHILD" use="concat(../@id, '+', @name)"/> 
    <xsl:key name="kEmplByAnc" match="EMPLOYEE" 
     use="concat(../../@id, '+', ../@name)"/> 

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

    <xsl:template match= 
     "ELEMENT 
     [generate-id() 
     = 
      generate-id(key('kElemById', @id)[1]) 
     ] 
     "> 
     <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select= 
     "../ELEMENT/CHILD 
      [generate-id() 
      = 
      generate-id(key('kChildByNameAndParentId', 
          concat(current()/@id, 
            '+', 
            @name 
           ) 
          )[1] 
         ) 
      ] 
     "/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="CHILD"> 
     <xsl:copy> 
     <xsl:apply-templates select= 
     "@* 
     | 
      key('kEmplByAnc', concat(../@id, '+', @name))"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ELEMENT"/> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<root> 
    <ELEMENT id="1" > 
     <CHILD name="aaa"> 
      <EMPLOYEE>Mark</EMPLOYEE> 
      <EMPLOYEE>John</EMPLOYEE> 
     </CHILD> 
     <CHILD name="bbb"> 
      <EMPLOYEE>Tom</EMPLOYEE> 
     </CHILD> 
    </ELEMENT> 
    <ELEMENT id="2" > 
     <CHILD name="aaa"> 
      <EMPLOYEE>leo</EMPLOYEE> 
      <EMPLOYEE>Jason</EMPLOYEE> 
     </CHILD> 
    </ELEMENT> 
    <ELEMENT id="1" > 
     <CHILD name="aaa"> 
      <EMPLOYEE>Tim</EMPLOYEE> 
     </CHILD> 
    </ELEMENT> 
</root> 

產生想要的,正確的結果

<root> 
    <ELEMENT id="1"> 
     <CHILD name="aaa"> 
     <EMPLOYEE>Mark</EMPLOYEE> 
     <EMPLOYEE>John</EMPLOYEE> 
     <EMPLOYEE>Tim</EMPLOYEE> 
     </CHILD> 
     <CHILD name="bbb"> 
     <EMPLOYEE>Tom</EMPLOYEE> 
     </CHILD> 
    </ELEMENT> 
    <ELEMENT id="2"> 
     <CHILD name="aaa"> 
     <EMPLOYEE>leo</EMPLOYEE> 
     <EMPLOYEE>Jason</EMPLOYEE> 
     </CHILD> 
    </ELEMENT> 
</root> 

說明:適當使用的Muenchian method for groupingkeys

+0

解決方案是完美的:)非常感謝你。 – 2012-03-10 18:14:56