2013-04-20 3 views
1

Переключившись с Fedora 17 на 18, я получаю различное поведение синтаксического анализа для одного и того же кода lxml, по-видимому, из-за разных версий базовых библиотек (версии libxml2 и libxslt изменены).Как управлять обработкой новой строки в функции lxml xpath text()?

Вот пример 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.

Есть ли способ контролировать это поведение? (Необязательный аргумент где-нибудь?) Или еще лучше, есть ли способ вернуть прежнее поведение с помощью новых библиотек?

ответ

1

в формате XML текст() возвращает текст внутри тегов как есть (unstripped), поэтому, если у вас есть пробельные символы, вкладки, новые строки, они будут включены.

Возможно, вы построили многострочную строку с + и \ 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.