<root>
  <parent>
    <child>
     <name>John</name>
    </child>
    <child>
      <name>Ben</name>
    </child>
  </parent>
  <parent>
    <child>
     <name>John</name>
    </child>
    <child>
     <name>Mark</name>
    </child>
    <child>
      <name>Luke</name>
    </child>
 </parent>
</root>

I want unique child nodes only i.e. only one child node if there is more than one with the same name.

Such as:

John Ben Mark Luke


我努力了:

<xsl:for-each select="parent">
  <xsl:for-each select="child[name != preceding::name]">
    <xsl:value-of select="name"/>
  </xsl:for-each>
</xsl:for-each>

But I get:

Ben Mark Luke


?!

最佳答案

您的问题是您正在使用!=运算符在值和节点集之间进行比较。

这是错误的-当比较中的操作数之一是节点集时,请始终避免使用!=运算符,并始终使用not()函数和=运算符。

以下是正确的解决方案:

<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:template match="/*">
    <xsl:for-each select="parent">
      <xsl:for-each select="child[not(name = preceding::name)]">
        <xsl:value-of select="concat(name, ' ')"/>
      </xsl:for-each>
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>


当此转换应用于提供的XML文档时:

<root>
  <parent>
    <child>
     <name>John</name>
    </child>
    <child>
      <name>Ben</name>
    </child>
  </parent>
  <parent>
    <child>
     <name>John</name>
    </child>
    <child>
     <name>Mark</name>
    </child>
    <child>
      <name>Luke</name>
    </child>
 </parent>
</root>


所需的正确结果产生了:

John Ben Mark Luke


说明:这是W3C XPath 1.0规范定义!=运算符的语义的方式:


“如果一个要比较的对象是
节点集,另一个是字符串,
那么如果
并且仅当在
节点集,使得
执行比较
节点和其他节点的字符串值
字符串是正确的。”


这意味着

's' != node-set


如果node-set中甚至只有一个不等于's'的节点,则始终为true。

这不是需要的语义。

另一方面,

not('s' = node-set())


仅当node-set中没有等于's'的节点时才为true。

这正是想要的比较。

请注意:您选择的分组技术是O(N ^ 2),并且仅应用于要去重复的很小的一组值。如果需要效率,则一定要使用Muenchian方法进行分组(讨论或演示这不在此问题的范围之内)。

关于xslt - XSLT,XPath唯一子节点唯一的问题是根本没有选择非唯一节点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4321811/

10-12 12:42
查看更多