在给定元素作为上下文的情况下,我想选择前一个兄弟元素并检查它是否具有特定名称。但是需要注意的是,如果存在具有非空白内容的插入文本节点,则不希望选择该节点。
例如,给定此XML文档...
“a2”和“a3”的结果是我困惑的地方。它能正确找到前面的
编辑:下面是我编写的XPath以及我的意图:
例如,给定此XML文档...
<r>
<a>a1</a><a>a2</a>
b
<a>a3</a>
<a>a4</a>
<b/>
<a>a5</a>
</r>
然后:
- 对于"a1",不应该有匹配(它之前没有立即相邻的
<a>
兄弟元素) - 对于"a2",应该匹配 "a1"(它之前没有文字节点)
- 对于"a3",不应该有匹配(它之前有一个非空白的文字节点)
- 对于"a4",应该匹配 "a3"(中间的文字节点只包含空格)
- 对于"a5",不应该有匹配(之前的兄弟元素不是
<a>
)。
我可以使用 preceding-sibling::*[1][name()="a"]
来检查之前的兄弟元素是否为 <a>
。
但是,我无法想出如何表示“选择下一个兄弟节点,无论是元素还是文本,然后查看它是否不是文本或 normalize-space(.)=""
”。我的最佳猜测是这样的:
preceding-sibling::*[1][name()="a"][following-sibling::node()[1][not(text()) or normalize-space(.)=""]]
...但似乎没有任何作用。
这是我的测试Ruby文件:
require 'nokogiri'
xpath = 'preceding-sibling::*[1][name()="a"][following-sibling::node()[1][not(text()) or normalize-space(.)=""]]'
fragment = Nokogiri::XML.fragment '<a>a1</a><a>a2</a> b <a>a3</a> <a>a4</a> <b/> <a>a5</a>'
fragment.css('a').each{ |a| p [a.text,a.xpath(xpath).to_s] }
#=> ["a1", ""]
#=> ["a2", ""]
#=> ["a3", "<a>a2</a>"]
#=> ["a4", "<a>a3</a>"]
#=> ["a5", ""]
“a2”和“a3”的结果是我困惑的地方。它能正确找到前面的
<a>
,但无法正确验证其后续第一个兄弟节点是否为文本(这应该允许“a2”找到“a1”),或者它是否只包含空格(这应该防止“a3”找到“a2”)。
编辑:下面是我编写的XPath以及我的意图:
preceding-sibling::*[1][name()="a"]…
- 找到第一个前面的元素,并确保它是<a>
。这似乎按预期工作。[following-sibling::node()[1][…]]
- 确保找到的前面的<a>
的第一个后续节点符合某些条件not(text()) or normalize-space(.)=""
- 确保此后续节点不是文本节点,或者其规范化空格为空
not(text()) or normalize-space(.)=""
必须是:not(self::text()) or normalize-space(.)=""
。 - Dimitre Novatchev