如何使用XSLT 2.0或XPath 2.0获取引用具有不同值的元素的href?

时间:2012-09-27 17:38:09

标签: 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</b>
<b id="h7">E5</b>

有没有办法使用XSLT2 / Xpath2来获取h1和h3引用不同的值E1和E2并忽略h2,因为它引用相同的值E1?

感谢。

3 个答案:

答案 0 :(得分:1)

使用,假设ab是顶级元素的子级:

   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>

在提供的XML文档上应用此转换时:

<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>

评估XPath表达式并将此评估结果复制到输出

h1 h3

<强>更新

正如Michael Kay所指出的,上述解决方案是O(N ^ 2),如果有很多b兄弟姐妹,可能会很慢。

这是一个至少线性(或更快)的XSLT 2.0解决方案:

<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>

同样,当此转换应用于同一XML文档(上图)时,会生成所需的正确结果

h1 h3

答案 1 :(得分:1)

你可以尝试这个XPath:

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

答案 2 :(得分:1)

我无法看到<a>元素扮演什么角色 - 在我看来问题只涉及b元素 - 我是否完全误解了它?

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

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

将返回h1 h2