Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prepend or append PI before / after the root element with lxml

With lxml, how can I prepend processing instructions before the root element or append PIs after de root element with lxml.

Currently, the following example doesn't work:

from lxml import etree

root = etree.XML("<ROOT/>")
root.addprevious(etree.ProcessingInstruction("foo"))
print(etree.tounicode(root))

I get:

<ROOT/>

Instead of:

<?foo?><ROOT/>
like image 528
Laurent LAPORTE Avatar asked Nov 25 '25 06:11

Laurent LAPORTE


1 Answers

Actually, an Element is always attached to a ElementTree even if it looks "detached":

root = etree.XML("<ROOT/>")
assert root.getroottree() is not None

When we use addprevious/addnext to insert a processing instruction before/after a root element, the PIs are not attached to a parent element (there isn't any) but they are attached to the root tree instead.

So, the problem lies in the usage of tounicode (or tostring). The best practice is to print the XML of the root tree, not the root element.

from lxml import etree

root = etree.XML("<ROOT/>")
root.addprevious(etree.ProcessingInstruction("foo"))
root.addnext(etree.ProcessingInstruction("bar"))

print(etree.tounicode(root))
# => "<ROOT/>"

print(etree.tounicode(root.getroottree()))
# => "<?foo ?><ROOT/><?bar ?>"
like image 53
Laurent LAPORTE Avatar answered Nov 27 '25 21:11

Laurent LAPORTE



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!