Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 如何基于重复节点的子节点删除重复节点?_Xml_Xslt_Xpath 2.0 - Fatal编程技术网

Xml 如何基于重复节点的子节点删除重复节点?

Xml 如何基于重复节点的子节点删除重复节点?,xml,xslt,xpath-2.0,Xml,Xslt,Xpath 2.0,假设我有以下顺序: <node-1> <children-A attr="100" /> </node-1> <node-1> <children-A attr="200" /> </node-1> <!--not a duplicate --> <node-1> <children-B /> </node-1> <node-1> <children-

假设我有以下顺序:

<node-1> <children-A attr="100" /> </node-1>
<node-1> <children-A attr="200" /> </node-1>     <!--not a duplicate -->
<node-1> <children-B /> </node-1>
<node-1> <children-B /> </node-1>                <!-- duplicate off the above -->
<node-1> <children-A /> <children-B /> </node-1> <!--not a duplicate -->

我希望获得所有唯一的“节点1”,以便输出为:

<node-1> <children-A attr="100" /> </node-1>
<node-1> <children-A attr="200" /> </node-1>
<node-1> <children-B /> </node-1>
<node-1> <children-A /> <children-B /> </node-1>

注意:仅删除了

使用Saxon 9.1.0.8,我尝试了
distinct value($S)
,但返回类型是
xs:anyAtomicType
,我不知道如何将其转换为正确的序列(如果可能的话!)

但是,我可以使用
count(distinct value($S))
来检查返回的元素数量是否与唯一元素的实际数量匹配,事实上它确实匹配。

使用(反过来使用,反过来使用XSLT/XPath 2.0函数
deep equal
)您可以使用

或者,如果不希望或无法包含functx库,则需要在中使用其代码

<xsl:variable name="distinct-seq"
  select="for $pos in (1 to count($your-sequence))
          return $your-sequence[$pos]
                               [not(some $node in $your-sequence[position() lt $pos] satisfies deep-equal(., $node))]"/>

使用(反过来使用,反过来使用XSLT/XPath 2.0函数
deep equal
)您可以使用

或者,如果不希望或无法包含functx库,则需要在中使用其代码

<xsl:variable name="distinct-seq"
  select="for $pos in (1 to count($your-sequence))
          return $your-sequence[$pos]
                               [not(some $node in $your-sequence[position() lt $pos] satisfies deep-equal(., $node))]"/>

这实际上是一个XPath 2.0问题。

使用

   for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:sequence select=
  "for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]

  "/>
 </xsl:template>
</xsl:stylesheet>
基于XSLT2.0的验证

   for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:sequence select=
  "for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]

  "/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下XML文档时(提供的片段包装到单个顶部元素中):


生成所需的正确结果:

<node-1>
   <children-A attr="100"/>
</node-1>
<node-1>
   <children-A attr="200"/>
</node-1>
<node-1>
   <children-B/>
</node-1>
<node-1>
   <children-A/>
   <children-B/>
</node-1>

这实际上是一个XPath 2.0问题。

使用

   for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:sequence select=
  "for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]

  "/>
 </xsl:template>
</xsl:stylesheet>
基于XSLT2.0的验证

   for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:sequence select=
  "for $vN in /*/*
     return
        $vN[not(/*/*[. >> $vN and deep-equal(., $vN)])]

  "/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下XML文档时(提供的片段包装到单个顶部元素中):


生成所需的正确结果:

<node-1>
   <children-A attr="100"/>
</node-1>
<node-1>
   <children-A attr="200"/>
</node-1>
<node-1>
   <children-B/>
</node-1>
<node-1>
   <children-A/>
   <children-B/>
</node-1>