2012-06-19 19 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")]') 
相关问题