Как добавить теговой текст к элементу из простой строки? - PullRequest
1 голос
/ 10 июля 2019

С помощью python lxml я хочу создать элемент etree.Element, содержимое которого взято из строки.У меня есть два случая:

  1. Это простая строка (например: «Hello world!»).
  2. Это строка с тегами, но все же, для Python это строкаи я не знаю заранее, что это помеченный (например: «Привет! ").

Как справиться со вторым случаем?

Вот наивный, не функционирующий способ:

>>> from lxml import etree
>>> string = "Hello <value-of select=\"world\"/>!"
>>> xml = etree.Element('root')
>>> xml.text = string
>>> etree.tostring(xml)
... b'<root>Hello &lt;value-of select="world"/&gt;!</root>'

Я хорошо знаю, что,если я знаю структуру моей строки, я должен использовать метод tail из etree.Element, как описано в учебном пособии по lxml . Итак, вот функционирующий, не обобщаемый способ:

>>> from lxml import etree
>>> xml2 = etree.Element('root')
>>> xml2.text = "Hello "
>>> valueof = etree.SubElement(xml2, 'value-of')
>>> valueof.set('select', 'world')
>>> valueof.tail = '!'
>>> etree.tostring(xml2)
... b'<root>Hello <value-of select="world"/>!</root>'

Но как сделать это автоматически, не зная заранее точную строку?

Я не знаю, как разобрать строку, чтобы можно было разбить ее части. Или, может быть, мне следует попробовать другой способ.

Я попробовал это:

>>> from lxml import etree
>>> from io import StringIO
>>> string="Hello <value-of select=\"world\"/>!"
>>> tree = etree.parse(StringIO(string))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "src/lxml/lxml.etree.pyx", line 3427, in lxml.etree.parse (src/lxml/lxml.etree.c:81117)
  File "src/lxml/parser.pxi", line 1828, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:118072)
  File "src/lxml/parser.pxi", line 1848, in lxml.etree._parseMemoryDocument (src/lxml/lxml.etree.c:118341)
  File "src/lxml/parser.pxi", line 1729, in lxml.etree._parseDoc (src/lxml/lxml.etree.c:116899)
  File "src/lxml/parser.pxi", line 1063, in lxml.etree._BaseParser._parseUnicodeDoc (src/lxml/lxml.etree.c:110886)
  File "src/lxml/parser.pxi", line 595, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:105109)
  File "src/lxml/parser.pxi", line 706, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:106817)
  File "src/lxml/parser.pxi", line 635, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:105671)
  File "<string>", line 1
lxml.etree.XMLSyntaxError: Start tag expected, '<' not found, line 1, column 1

Но так как etree.parse требует правильно сформированного xml и нет корневого элемента, он терпит неудачу. Поэтому я попробовал это, надеясь, что он будет менее строгим:

>>> tree = etree.parse(StringIO(string), etree.XMLParser(recover=True))
>>> etree.tostring(tree)

но вывод пуст, поэтому кажется, что я не могу разобрать мою строку, чтобы добавить результирующее дерево к существующему ... Именно так мне нужно делать вещи, потому что я сочиняю свой xmlс нуля.

Вернуться к моему вопросу: как справиться с двумя делами, которые япредставлен ранее?

1 Ответ

0 голосов
/ 10 июля 2019

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

from lxml import etree

simple = "Hello world!"
tagged = "Hello <value-of select=\"world\"/>!"

xml1 = "<root>" + simple + "</root>"
xml2 = "<root>" + tagged + "</root>"

# fromstring() returns an Element object 
elem1 = etree.fromstring(xml1) 
elem2 = etree.fromstring(xml2) 
...