2013-08-26 51 views
1

使用XPath(.NET),我试图选择不包含任何文本节点的所有节点。查找没有任何文本节点的所有节点

鉴于此文件:

<root> 
    <node1> 
    <node1a>Node 1A</node1a> 
    </node1> 
    <node2>Node 2</node2> 
    <node3> 
    <node3a>Node 3A</node3a> 
    <node3b></node3b> 
    </node3> 
    <node4></node4> 
    <node5> 
    <node5A></node5A> 
    </node5> 
</root> 

我tyring得到节点:

<node3b></node3b> 

<node4></node4> 

<node5> 
    <node5A></node5A> 
</node5> 

注意重叠的子树被合并,所以node5A不应单独返回。

我希望它可以拉的伎俩,但由于某种原因(这可能是显而易见的,当有人指出它)不:

//*[count(//text()) = 0] 

注:我使用XPath tester尝试的事情出。

回答

1

假设你的结果例子真的是你想要的东西(这是不是完全按照在冠军语句)以上

//*[count(.//text()) = 0] 

或首选的方式的建议

//*[not(.//text())] 

不工作结果不是你所期望的

<node3b /> 
<node4 /> 
<node5> 
    <node5A /> 
</node5> 
<node5A /> <!-- this node is not present in your example --> 

如果你想要的是所有s没有任何文本节点ubtrees不包括在其他所得的子树的溶液是这样的一个

//*[not(.//text())][not(ancestor::*[not(.//text())])] 

第二谓词从结果所有这些具有至少一个祖先已经包含在结果中的节点

+0

那里好挑剔;)我确实需要合并子树,所以我编辑了这个问题。 –

2

精氨酸......和刚发布的时候,解决作物起来:

//*[count(.//text()) = 0] 

说明:条件count(//text()) = 0计数从根本上,这始终是大于零的所有文本节点。要从当前节点计数,我需要以点为前缀:count(.//text()) = 0

请注意@jvverde正确地指出节点可以在结果集中多次出现。所以这个表达式是不是我提的条件完全匹配,如node5A是有两次:

<node3b></node3b> 

<node4></node4> 

<node5> 
    <node5A></node5A> 
</node5> 

<node5A></node5A> 
1

你也可以使用//*[.='']尽可能空元素应该有空字符串值。

+2

这需要除去首先计算数据字符串,并且可能比计算文本节点更昂贵。 –

0

您也可以使用更简单,可读

//*[not(.//text())] 

,或者如果您希望通过empty(...)更换not(...)

两者都已经过优化,所以即使简单的XPath实现也应该能够以“快速失败”的方式实现它们(找到一个文本节点,将谓词评估为false)。

+0

在我意识到我的表情中罪魁祸首之前,我做了一些“不”的试验。我会尝试你的建议,所以你可能会得到奖励;) –