删除重复元素并使用xslt收集所有子节点

时间:2012-03-09 21:53:46

标签: 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>

我尝试做的是收集“EMPLOYEE”同时具有相同的“ELEMENT”ID和“CHILD”名称并删除重复的“ELEMENT”和“CHILD”。

我的意思是我只需要一个只有一个但所有员工都属于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 个答案:

答案 0 :(得分: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 grouping keys