Xml 如何使用XSLT2.0或XPath2.0获取引用具有不同值的元素的HREF?

Xml 如何使用XSLT2.0或XPath2.0获取引用具有不同值的元素的HREF?,xml,xslt,xpath,xpath-2.0,Xml,Xslt,Xpath,Xpath 2.0,我有以下XML输入 <a href="h1" /> <a href="h2" /> <a href="h3" /> <b id="h1">E1</b> <b id="h2">E1</b> <b id="h3">E2</b> <b id="h4">E3</b> <b id="h5">E3</b> <b id="h6">E4<

我有以下XML输入

<a href="h1" />
<a href="h2" />
<a href="h3" />

<b id="h1">E1</b>
<b id="h2">E1</b>
<b id="h3">E2</b>
<b id="h4">E3</b>
<b id="h5">E3</b>
<b id="h6">E4</b>
<b id="h7">E5</b>

E1
E1
E2
E3
E3
E4
E5
有没有办法使用XSLT2/Xpath2只获取h1和h3,它们引用不同的值E1和E2,而忽略h2,因为它引用相同的值E1


谢谢。

使用,假设
a
b
是顶层元素的子元素:

   for $href in /*/a/@href,
       $b in /*/b[@id = $href and not(. = preceding-sibling::b)]
     return
       string($href)
基于XSLT-2的验证

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

 <xsl:template match="/">
     <xsl:sequence select=
      "for $href in /*/a/@href,
           $b in /*/b[@id = $href and not(. = preceding-sibling::b)]
          return
             string($href)
      "/>
 </xsl:template>
</xsl:stylesheet>
h1 h3
h1 h3
更新

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

 <xsl:template match="/">
     <xsl:sequence select=
      "for $href in /*/a/@href,
           $b in /*/b[@id = $href and not(. = preceding-sibling::b)]
          return
             string($href)
      "/>
 </xsl:template>
</xsl:stylesheet>
h1 h3
h1 h3
正如Michael Kay所指出的,上述解决方案是O(N^2),如果有许多
b
兄弟姐妹,则速度可能会很慢

这里有一个XSLT2.0解决方案,它至少是线性的(或更快):

<html>
    <a href="h1" />
    <a href="h2" />
    <a href="h3" />
    <b id="h1">E1</b>
    <b id="h2">E1</b>
    <b id="h3">E2</b>
</html>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kReferrer" match="b" use="@id"/>

 <xsl:template match="/*">
   <xsl:for-each-group select="key('kReferrer', a/@href)" group-by=".">
     <xsl:sequence select="string(@id)"/>
   </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

您可以尝试以下XPath:

/*/b[@id = /*/a/@href and not(preceding::b = .)]

我很难看到
元素扮演什么角色-在我看来,问题只涉及
b
元素-我是否完全误解了它

给定输入,将给定节点的父节点作为上下文项

<xsl:for-each-group select="b" group-by=".">
  <xsl:value-of select="current-group()[1]/@id"/>
</xsl:for-each-group>


将返回h1 h2

Ouch-在谓词中使用前面的轴-这是文档大小的二次性能。完全没有必要。虽然我们不知道这个文档有多大,但这是另一个二次解决方案——毫无必要。但您对需求的理解似乎与我不同,因为您的解决方案涉及到查看
a
元素,而我的解决方案不涉及这些元素。@MichaelKay,我认为DevNull和我都想提供一个纯XPath 2.0解决方案,并将此问题理解为XPath挑战。至于您的解决方案,我认为您不太了解需求——只应选择从
a
s引用的
b
。所以,这会有点复杂。很抱歉强加给你迪米特,但我知道你喜欢一个很好的挑战:)。这是不是有一个雪球的机会在地狱被回答@凯文,你什么意思?有三个很好的答案,我的答案及其最新更新既高效又紧凑。@Kev,我认为其他问题应该结束。答案很简单,一些必需的文件没有放在必要的相对位置。我不认为这对任何人都有用。谢谢你的回答。我的目标是获取引用不同元素的元素。元素的数量远远少于s,我编辑了我的问题以反映这一点。对不起,问题不太完整。