簡體   English   中英

如何在xpath中使用contains(text(),)時獲取兄弟姐妹

[英]How to get siblings when using contains(text(), ) in xpath

我今天已經介紹過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::* ,也可以。

那么,我怎樣才能讓兄弟姐妹處於這種狀態?

提前致謝。

你有趣的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. follow-sibling將返回所有兄弟姐妹,而不僅僅是直接兄弟姐妹。 因此,如果之后有節點,那么它們也將被返回。
  2. HTML不是XML。 雖然LXML會嘗試為您清理源代碼,但如果您不能相信傳入的HTML是干凈的,那么您的XPath可能會失敗。 例如。 我相信標題標簽不需要在HTML中關閉標簽,因此根據源的破壞程度,LXML可能會錯誤地將其作為子項,這可能會破壞XPath
  3. 標題不能包含子元素,這可能會影響LXML清理它的方式(例如在它們之間添加正文標記等)。

在XML編輯器中對此進行測試表明您的XPath是有效的,但是在LXML中進行測試時我得到的元素不足,這可能意味着它正在改變XML(但我沒有檢查)。

如果XPath是這項工作的工具,我建議重新考慮,特別是如果你試圖用它來搜索網頁或類似的東西。

您可能還會考慮重寫XPath語句,以便它更具可讀性。

//*[contains(text(),'some_text')]/following-sibling::*

這說:找到任何在文本中有“一些文本”的元素,然后得到下一個兄弟姐妹。

//*[preceding-sibling::*[position()=1 and contains(text(),'some_text') and ]]

雖然這說:找到我的第一個兄弟的文本包含“一些文本”的元素。

這可能是一個樣式問題,但我發現后者更具可讀性。

<?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應該是相同的。

這里的關鍵是你的XPath正在查看由HTML5解析器創建的樹,而不是XML解析器。 HTML5解析器在樹中創建在源中不明確的節點:實際上,它們修復無效的HTML並將其轉換為有效的HTML。 無論您使用XPath,JQuery還是直接DOM API,這都會影響導航HTML樹的任何嘗試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM