【问题标题】:How to control newline processing in the lxml xpath text() function?如何控制 lxml xpath text() 函数中的换行符处理?
【发布时间】:2013-04-20 17:37:07
【问题描述】:

从 Fedora 17 切换到 18 后,对于相同的 lxml 代码,我得到了不同的解析行为,这显然是由于底层库的不同版本(libxml2 和 libxslt 版本发生了变化)。

以下是两个版本的不同结果的 lxml 代码示例:

from io import BytesIO
from lxml import etree

myHtmlString = \
    '<!doctype html public "-//w3c//dtd html 4.0 transitional//en">\r\n'+\
    '<html>\r\n'+\
    '<head>\r\n'+\
    '   <title>Title</title>\r\n'+\
    '</head>\r\n'+\
    '<body/>\r\n'+\
    '</html>\r\n'
myFile = BytesIO(myHtmlString)
myTree = etree.parse(myFile, etree.HTMLParser())
myTextElements = myTree.xpath("//text()")
myFullText = ''.join([myEl for myEl in myTextElements])

assert myFullText == 'Title', repr(myFullText)

f17 版本通过断言,即xpath("//text()") 只返回文本'Title',而 f18 版本失败并输出

Traceback (most recent call last):
  File "TestLxml.py", line 17, in <module>
    assert myFullText == 'Title', repr(myFullText)
AssertionError: '\r\n\r\n   Title\r\n\r\n\r\n'

显然,f18 版本处理换行符和空格的方式与 f17 版本不同。

有没有办法控制这种行为? (某处的可选参数?) 或者更好的是,有没有一种方法可以让我使用新库恢复旧行为?

【问题讨论】:

    标签: python xpath newline lxml carriage-return


    【解决方案1】:

    在 XML 中,text() 按原样返回标签内的文本(未剥离),因此如果您有任何空白字符、制表符、换行符,它们将被包括在内。

    可能是你用 + 和 \n\r 构造多行字符串的方式不小心测试了两个不同的字符串。

    如果您将字符串更改为如下例所示的三引号字符串并对其进行测试。

    from io import BytesIO
    from lxml import etree
    
    
    html = '''
        <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
        <html>
        <head>
           <title>Title</title>
        </head>
        <body/>
        </html>
    '''
    tree = etree.parse(BytesIO(html), etree.HTMLParser())
    text_elements = tree.xpath("//text()")
    full_text = ''.join(text_elements)
    assert full_text == 'Title', repr(full_text)
    

    您还可以看到,用空格或换行符包围文本使它们成为 text() 函数返回的一部分。请参阅下面的title

    html = '''
    <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
    <html>
    <head>
       <title>   Title   </title>
    </head>
    <body/>
    </html>
    '''
    tree = etree.parse(BytesIO(html), etree.HTMLParser())
    text_elements = tree.xpath("//text()")
    full_text = ''.join(text_elements)
    assert full_text == '   Title   ', repr(full_text)
    

    如果你不需要空格,你可以自己在字符串上调用 strip()。如果您确定即使您的标签不包含空格,您也会收到空格,那么您应该将其报告为 lxml mailing list 上的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多