1

如何排除节点的特定后代?在这个方向上,表达式 *[not(self::nodetag)] 似乎只是在节点的子级别进行区分,接受返回的节点集中的所有其他后代。我想要一个表达式来选择 div 下的所有节点,但那些不是 a 的节点,请参见下面的示例。树结构必须保持不变。

@Dimitri Novatchev 发布的方法似乎是正确的,但不适用于 HAP 实施:

使用此示例文档:

<div>
  <span>
     <a>lala</a>
  </span>
</div>

HAP 将返回以下结构及其建议的表达式 /div/descendant::node()[not(self::a)]

<div>
  <span>
     <a>lala</a>
  </span>
</div>
<span>
     <a>lala</a>
 </span>

如果除了嵌套的跨度之外还有另一个标签,它也会将它作为单独的树返回,有人知道这种奇怪的行为吗?它是一个 HAP 错误吗?

谢谢

4

2 回答 2

1

我想要一个表达式来选择 div 下的所有节点,但那些不是a. 树结构必须保持不变。

使用

/div/descendant::node()[not(self::a)]

div这将选择(后代)不是的顶部元素的任何后代a

基于 XSLT 的验证

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:for-each select="/div/descendant::node()[not(self::a)]">
    <xsl:value-of select="concat('&#xA;', position(), '. &quot;')"/>
    <xsl:copy-of select="."/>"
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

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

<div>
    <span>
        <a>lala</a>
    </span>
</div>

评估 XPath 表达式,并以适当的格式输出所有选定的节点,以使它们清晰可见

1. "
    "

2. "<span>

   <a>lala</a>

</span>"

3. "
        "

4. "lala"

5. "
    "

6. "
"

正如我们所见,选择了 6 个节点——一个span元素、四个纯空白文本节点和一个非纯空白文本节点——它们都不是a.

更新

在评论中,OP 澄清说他实际上希望将 XML 文档转换为另一个,其中aa 的任何后代都div被省略。

这是一种这样的转变

<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="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="div//a"/>
</xsl:stylesheet>

当将此转换应用于同一个 XML 文档(上图)时,会产生(我猜是)想要的结果

<div>
   <span/>
</div>

如果我们只想产生任何div具有后代的a后代,那么我们需要几乎相同的转换:

<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="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="div[.//a]"><xsl:apply-templates/></xsl:template>
 <xsl:template match="div//a"/>
</xsl:stylesheet>

应用到与上述相同的 XML 文档的结果是:

<span/>
于 2012-07-22T19:24:00.760 回答
1

@Devela:您将 XPath 表达式选择的节点集与发出请求的应用程序显示它们的方式混淆了。应用程序通过显示以该节点为根的整个子树来显示该节点是很常见的。因此,如果您的查询是 //div,并且选定的 div 元素之一包含一个<a>节点作为后代,则将显示包含该<a>元素的结果。您无法通过更改 XPath 表达式来更改它,因为 XPath 表达式没有选择<a>元素;您只能通过更改结果的显示方式来更改它。

现在,如果您想显示一个与源中的元素<div>类似的元素,只是省略了 ,那么您就超出了 XPath 可以做的范围。XPath 只能选择输入树中节点的子集,它不能创建修改后的树。为此,您需要 XSLT 或 XQuery。<div><a>

于 2012-07-22T21:45:54.637 回答