Как правильно экранировать одинарные и двойные кавычки

У меня есть объект lxml etree HTMLParser, с которым я пытаюсь создать xpaths, чтобы утверждать xpaths, атрибуты xpath и текст этого тега. Я столкнулся с проблемой, когда текст тега заключен либо в одинарные ('), либо в двойные (") кавычки, и я исчерпал все свои варианты.

Вот образец объекта, который я создал

parser = etree.HTMLParser()
tree = etree.parse(StringIO(<html><body><p align="center">Here is my 'test' "string"</p></body></html>), parser)

Вот фрагмент кода, а затем различные варианты переменной, считываемой в

   def getXpath(self)
     xpath += 'starts-with(., \'' + self.text + '\') and '
     xpath += ('count(@*)=' + str(attrsCount) if self.exactMatch else "1=1") + ']'

self.text в основном является ожидаемым текстом тега, в данном случае: Вот моя «тестовая» «строка»

это не удается, когда я пытаюсь использовать метод xpath объекта HTMLParser

tree.xpath(self.getXpath())

Причина в том, что полученный xpath выглядит следующим образом: '/html/body/p[starts-with(.,'Вот мой 'тест' "строка"') и 1=1]'

Как я могу правильно избежать одинарных и двойных кавычек из переменной self.text? Я пробовал использовать тройные кавычки, обертывать self.text в repr() или делать re.sub или string.replace, экранируя ' и " с помощью \' и \"


person Bob Evans    schedule 18.10.2011    source источник


Ответы (3)


Судя по тому, что мы видим в Википедии и школа w3, вы не должны использовать ' и " в содержимом узлов, даже если только < и & считаются строго незаконными. Они должны быть заменены соответствующими «предопределенными ссылками на сущности», то есть &apos; и &quot;.

Кстати, парсеры Python, которые я использую, позаботятся об этом прозрачно: при написании они заменяются; при чтении они конвертируются.

После второго прочтения вашего ответа я протестировал некоторые вещи с ' и т. д. в интерпретаторе Python. И он убежит от всего для вас!

>>> 'text {0}'.format('blabla "some" bla')
'text blabla "some" bla'
>>> 'ntsnts {0}'.format("ontsi'tns")
"ntsnts ontsi'tns"
>>> 'ntsnts {0}'.format("ontsi'tn' \"ntsis")
'ntsnts ontsi\'tn\' "ntsis'

Итак, мы видим, что Python правильно экранирует вещи. Не могли бы вы затем скопировать и вставить полученное сообщение об ошибке (если оно есть)?

person Joël    schedule 18.10.2011
comment
Я вижу, ошибка, которую я получаю, связана с lxml: XPathEvalError: Invalid expression, трассировка стека — это файл lxml.etree.pyx, строка 2029, в lxml.etree._ElementTree.xpath (src/lxml/lxml.etree.c: 45934) Файл xpath.pxi, строка 379, в lxml.etree.XPathDocumentEvaluator.__call__ (src/lxml/lxml.etree.c:114389) Файл xpath.pxi, строка 242, в lxml.etree._XPathEvaluatorBase._handle_result (src/ lxml/lxml.etree.c:113063) Файл xpath.pxi, строка 228, в lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:112935) - person Bob Evans; 18.10.2011
comment
ммх, ошибка возникает из-за lxml, потому что выражение считается недопустимым. Не могли бы вы вставить значение xpath при рендеринге print? - person Joël; 18.10.2011
comment
экранирование ' и с соответствующими объектами HTML сделало свое дело. Я очень устал прошлой ночью и не думал, что строка на самом деле была проанализирована HTML. Спасибо за это руководство - person Bob Evans; 18.10.2011
comment
Отлично, вот что я подумал: lxml не очень нравится, когда эти символы используются непосредственно в контенте. Не за что - пожалуйста, не забудьте принять ответ! - person Joël; 18.10.2011
comment
Проблема в том, что мне пришлось отказаться от этого, потому что это вызывало много головной боли. Позже я столкнулся с проблемой, что href с подчеркиванием не мог вернуть правильный xpath, но только при написании модульного теста он отлично работал в самой оболочке python. Также я имел дело с ужасным HTML, и я также нашел недопустимые символы в атрибутах alt. Таким образом, с небольшими пробами и ошибками у меня все работает, но я удалил start-with часть xpath и утвердил текст тега отдельно - person Bob Evans; 19.10.2011

есть больше вариантов на выбор, особенно """ и ''' могут быть тем, что вам нужно.

s = "a string with a single ' quote"
s = 'a string with a double " quote'
s = """a string with a single ' and a double " quote"""
s = '''another string with those " quotes '.'''
s = r"raw strings let \ be \"
s = r'''and can be added \ to " any ' of """ those things'''
s = """The three-quote-forms
       may contain
       newlines."""
person towi    schedule 18.10.2011

Решение применимо, если вы используете python lxml. Лучше оставить экранирование для lxml. Мы можем сделать это, используя lxmlvariables. Предположим, у нас есть xpath, как показано ниже:

//tagname[text='some_text']`

Если some_text имеет как одинарные, так и двойные кавычки, то это вызывает "Invalid Predicate error". Ни бегство от работы для меня, ни тройные кавычки. Потому что xml не принимает тройные кавычки.

Решение, которое у меня сработало, это lxml переменных.

Мы конвертируем xpath, как показано ниже:

//tagname[text = $var]

Затем выполните

find = etree.XPath(xpath)

Затем оцените эту переменную до ее значения

elements = find(root, {'var': text})
person Hemanth Sharma    schedule 23.01.2020