Reputation: 565
I am using lxml in an attempt to to output the following xml code:
<annotation>
<folder>images</folder>
<filename>IMG_8111.JPG</filename>
<size>
<width>400</width>
<height>400</height>
</size>
<segmented>0</segmented>
<object>
<name>Bottle</name>
<bndbox>
<xmin>16</xmin>
<ymin>71</ymin>
<xmax>390</xmax>
<ymax>323</ymax>
</bndbox>
</object>
</annotation>
Im using this tutorial to learn how to implement lxml for my needs. The issue I am facing is that my desired output has subelements to subelements. For instance - <annotation>
is my main element, and then <folder>
, <filename>
and <size>
are subelements, but then, <height>
and <width>' are subelements to the
` subelements. How do I make this happen with lxml. I have the following so far:
from lxml import etree
import xml.etree.cElementTree as ET
root = etree.Element("annotation")
etree.SubElement(root, "folder").text = "Child 1"
etree.SubElement(root, "filename").text = "Child 2"
size = etree.SubElement(root, "size").text = "Child 3"
etree.SubElement(size, "width").text = "Child 4"
with open ('xmltree.xml', 'wb') as f:
f.write(etree.tostring(root, pretty_print = True))
But it throws the following error:
etree.SubElement(size, "width").text = "Child 4"
TypeError: Argument '_parent' has incorrect type (expected lxml.etree._Element, got str)
Please help me out on what I am doing wrong and how to proceed.
Upvotes: 0
Views: 5343
Reputation: 9010
In order for size = etree.SubElement(root, "size").text = "Child 3"
to be evaluated as you expect it to be, it would have to be interpreted as:
(size = etree.SubElement(root, "size")).text = "Child 3"
In Python, you can't perform an assignment in an expression. Instead, the way Python interprets this is:
size = "Child 3"
etree.SubElement(root, "size").text = "Child 3"
You could rewrite your code using two separate lines to achieve your desired result:
size = etree.SubElement(root, "size")
size.text = "Child 3"
After looking through the lxml
API, it does not appear to be a way way to both create an element and assign a value to the text
attribute in a single line.
Upvotes: 2
Reputation: 21
Your variable size has type string because it has "child 3" value. You should do:
size = etree.SubElement(root,"size")
size.text = "child 3"
etree.SubElement(size, "width").text="child 4"
Upvotes: 1