排除上次出现的重复节点。重复节点是具有多个具有相同值的属性的节点

时间:2010-12-29 12:56:42

标签: xml xslt xpath

我一直在尝试为我的检测和消除重复节点的问题编写XPath / XSLT。就我而言,重复节点是具有多个具有相同值的属性的节点。我想要消除重复的方法是排除重复节点的最后一次出现。如果有其他方法,请通知。

请注意:重复节点=具有相同值operator1,operator2和operator3属性的节点。

XML:

<data id = "root">
  <record id="1" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="2" operator1='abc' operator2='yyy' operator3='zzz'/>
  <record id="3" operator1='abc' operator2='yyy' operator3='zzz'/>
  <record id="4" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="5" operator1='xxx' operator2='lkj' operator3='tyu'/>
  <record id="6" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="7" operator1='abc' operator2='yyy' operator3='zzz'/>
  <record id="8" operator1='abc' operator2='yyy' operator3='zzz'/>
  <record id="9" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="10" operator1='rrr' operator2='yyy' operator3='zzz'/>
</data>

我需要的输出:

<data id = "root">
  <record id="1" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="2" operator1='abc' operator2='yyy' operator3='zzz'/>
  <record id="3" operator1='abc' operator2='yyy' operator3='zzz'/>
  <record id="4" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="6" operator1='xxx' operator2='yyy' operator3='zzz'/>
  <record id="7" operator1='abc' operator2='yyy' operator3='zzz'/>
</data>

我最接近的是这个Xpath,但它不能正常工作。

"//record[(./@operator1 = following-sibling::record/@operator1) and (./@operator2 = following-sibling::record/@operator2) and (./@operator3 = following-sibling::record/@operator3)]".

我搜索了整个互联网,但没有任何运气。任何帮助真的很感激。非常感谢。

2 个答案:

答案 0 :(得分:1)

  

我一直在努力写一篇   XPath / XSLT我的检测问题   并消除重复的节点。在我的   case,重复节点是带有的节点   具有相同值的多个属性。   我希望消除重复的方式   是通过排除最后一次出现的   重复的节点。如果,请建议   还有其他方法。

     

请注意:重复节点=具有的节点   operator1,operator2的值相同   和operator3属性。

这是重复节点消除的冲突定义

通过删除重复序列的最后一个来消除重复的节点。您想要的结果:

<data id = "root">
    <record id="1" operator1='xxx' operator2='yyy' operator3='zzz'/>
    <record id="2" operator1='abc' operator2='yyy' operator3='zzz'/>
    <record id="3" operator1='abc' operator2='yyy' operator3='zzz'/>
    <record id="4" operator1='xxx' operator2='yyy' operator3='zzz'/>
    <record id="6" operator1='xxx' operator2='yyy' operator3='zzz'/>
    <record id="7" operator1='abc' operator2='yyy' operator3='zzz'/>
</data>

仍然包含重复项,例如record s,ID(1,4和6)和(2,3和7)

正确删除重复项,也称为重复数据删除,只需要从所有重复项中留下一项。传统上,这是通过使用Muenchian方法进行分组在XSLT 1.0中完成的:

<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="kRecByAtts" match="record"
  use="concat(@operator1,'***',
              @operator2,'***',
              @operator3)"/>

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

 <xsl:template match=
  "record
      [not(generate-id()
      =
       generate-id(key('kRecByAtts',
                       concat(@operator1,'***',
                              @operator2,'***',
                              @operator3)
                       )[1]
                   )
            )
       ]
  "/>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<data id = "root">
    <record id="1" operator1='xxx' operator2='yyy' operator3='zzz'/>
    <record id="2" operator1='abc' operator2='yyy' operator3='zzz'/>
    <record id="3" operator1='abc' operator2='yyy' operator3='zzz'/>
    <record id="4" operator1='xxx' operator2='yyy' operator3='zzz'/>
    <record id="6" operator1='xxx' operator2='yyy' operator3='zzz'/>
    <record id="7" operator1='abc' operator2='yyy' operator3='zzz'/>
</data>

产生了想要的正确结果

<data id="root">
   <record id="1" operator1="xxx" operator2="yyy" operator3="zzz"/>
   <record id="2" operator1="abc" operator2="yyy" operator3="zzz"/>
</data>

答案 1 :(得分:0)

以下是一个示例XSLT 1.0样式表,它消除了最后一个重复的“记录”元素:

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

  <xsl:key name="k1" match="record" 
           use="concat(@operator1, '|', @operator2, '|', @operator3)"/>

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

  <xsl:template match="record[generate-id() 
                              = 
                              generate-id(key('k1', 
                                              concat(@operator1, '|', 
                                                     @operator2, '|', 
                                                     @operator3))[last()])]"/>

</xsl:stylesheet>