2012-06-19 23 views
3

當我使用contains查找元素的text()中數據的存在時,它適用於純數據,但不適用於元素內容中有回車符,新行/標記的情況。如何使//td[contains(text(), "")]在這種情況下工作?謝謝!如何使用Python在多行文本中搜索XPath中的內容?

XML:

<table> 
    <tr> 
    <td> 
     Hello world <i> how are you? </i> 
     Have a wonderful day. 
     Good bye! 
    </td> 
    </tr> 
    <tr> 
    <td> 
     Hello NJ <i>, how are you? 
     Have a wonderful day.</i> 
    </td> 
    </tr> 
</table> 

的Python:

>>> tdout=open('tdmultiplelines.htm', 'r') 
>>> tdouthtml=lh.parse(tdout) 
>>> tdout.close() 
>>> tdouthtml 
<lxml.etree._ElementTree object at 0x2aaae0024368> 
>>> tdouthtml.xpath('//td/text()') 
['\n  Hello world ', '\n  Have a wonderful day.\n  Good bye!\n ', '\n  Hello NJ ', '\n '] 
>>> tdouthtml.xpath('//td[contains(text(),"Good bye")]') 
[] ##-> But *Good bye* is already in the `td` contents, though as a list. 
>>> tdouthtml.xpath('//td[text() = "\n  Hello world "]') 
[<Element td at 0x2aaae005c410>] 

回答

3

使用

//td[text()[contains(.,'Good bye')]] 

說明

的原因的問題不在於文本節點的字符串值是一個多字符串 - 真正的原因是,td元素有一個以上的文本 - 節點的孩子。

在所提供的表達

//td[contains(text(),"Good bye")] 

傳遞給函數第一個參數是一個節點集合多於一個文本節點的。

根據XPath 1.0規範(在XPath 2.0中,這簡單地引發了一個類型錯誤),一個函數的求值需要一個字符串參數,但是通過一個節點集,只接受第一個字符串的值節點集中的節點。

在此特定情況下,所述傳遞的節點集的第一個文本節點具有字符串值

" 
       Hello world " 

因此比較失敗,並且希望td元件未選擇

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:copy-of select="//td[text()[contains(.,'Good bye')]]"/> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<table> 
     <tr> 
     <td> 
      Hello world <i> how are you? </i> 
      Have a wonderful day. 
      Good bye! 
     </td> 
     </tr> 
     <tr> 
     <td> 
      Hello NJ <i>, how are you? 
      Have a wonderful day.</i> 
     </td> 
     </tr> 
</table> 

XPath表達式求值和所選擇的節點(在這種情況只是一個)被複制到輸出

<td> 
      Hello world <i> how are you? </i> 
      Have a wonderful day. 
      Good bye! 
     </td> 
+0

感謝您的解釋! //td[text()[contains(.,'Good bye')]]類似於//td[contains(.," Good bye「)],因爲我看到它。選擇這個答案來幫助我和其他人理解這一點! – ThinkCode

+0

@ThinkCode:不客氣。實際上,'//td[contains(.," Good bye「)]'可能會導致誤報,因爲'.'被轉換爲上下文節點的*字符串值*。如果元素具有多個文本節點後代,則所有元素都將連接起來形成其字符串值。如果有兩個連續的文本節點後代,搜索字符串的起始子字符串中的第一個結尾和第二個搜索字符串的其餘部分開始,您可能不希望選中一個元素。 –

+0

嗯,我有點困惑。你能給我們舉一個例子來說明兩種實現之間的區別嗎?非常感謝! – ThinkCode

1

使用.,而不是text()

tdouthtml.xpath('//td[contains(.,"Good bye")]') 
相關問題