我今天已经介绍过xpath,它似乎非常强大,但经过相当多的搜索后,我还没有找到如何在使用contains时检索兄弟姐妹(通过follow-sibling和previous-sibling):
text = """
<html>
<head>
<title>This tag includes 'some_text'</title>
<h2>A h2 tag</h2>
</head>
</html>
"""
import lxml.html
doc = lxml.html.fromstring(text)
a = doc.xpath("//*[contains(text(),'some_text')]/following-sibling::*")
产生[]
。当然,我期望的结果是获得h2标签。
但是,使用*[contains(text(),'name')]
按预期检索title
元素。以同样的方式,如果不是使用跟随兄弟轴(我认为它是如何调用的),我使用//parent::*
,也可以。
那么,我怎样才能让兄弟姐妹处于这种状态?
提前致谢。
答案 0 :(得分:7)
你有趣的html示例。
import lxml
text = """
<html>
<body>
<span>This tag includes 'some_text'</span>
<h2>A h2 tag</h2>
</body>
</html>
"""
doc = lxml.etree.fromstring(text, parser=lxml.etree.HTMLParser())
doc.xpath("//*[contains(text(),'some_text')]/following-sibling::*")
# [<Element h2 at 102eee100>]
doc = lxml.html.fromstring(text)
doc.xpath("//*[contains(text(),'some_text')]/following-sibling::*")
# [<Element h2 at 102f6f188>]
更新:
这里我不使用html
解析器及其验证规则,并将输入视为随机xml:
text = """
<html>
<head>
<title>This tag includes 'some_text'</title>
<h2>A h2 tag</h2>
</head>
</html>
"""
doc = lxml.etree.fromstring(text)
doc.xpath("//*[contains(text(),'some_text')]/following-sibling::*[1]")
# [<Element h2 at 102eeef70>]
答案 1 :(得分:1)
在回答这个问题之前,有一些事情需要澄清:
在XML编辑器中对此进行测试表明您的XPath是有效的,但是在LXML中进行测试时我得到的元素不足,这可能意味着它正在改变XML(但我没有检查)。
如果XPath是这项工作的工具,我建议重新考虑,特别是如果你试图用它来搜索网页或类似的东西。
您也可以考虑重写XPath语句,以便它更具可读性。
//*[contains(text(),'some_text')]/following-sibling::*
这说:找到任何在文本中包含“some text”的元素,然后获得下一个兄弟姐妹。
//*[preceding-sibling::*[position()=1 and contains(text(),'some_text') and ]]
虽然这样说:找到我的第一个兄弟的文本包含“某些文字”的元素。
这可能是一个样式问题,但我发现后者更具可读性。
答案 2 :(得分:1)
<?xml version="1.0" ?>
<html>
<head>
<title>This tag includes 'some_text'</title>
<h2>A h2 tag</h2>
</head>
</html>
//*[contains(text(),'some_text')]/following-sibling::*
Array
(
[0] => SimpleXMLElement Object
(
[0] => A h2 tag
)
)
我使用的是PHP SimpleXMLElement,但xpath应该是相同的。
答案 3 :(得分:0)
这里的关键是你的XPath正在查看由HTML5解析器创建的树,而不是XML解析器。 HTML5解析器在树中创建在源中不明确的节点:实际上,它们修复无效的HTML并将其转换为有效的HTML。这会影响任何导航HTML树的尝试,无论您使用的是XPath,JQuery还是直接的DOM API。