Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add attributes to SubElement in ElementTree (Python)

I successfully added a new node to an Element using PY's ElementTree. I now try to give it attributes, which fails, despite I'm following the tutorial.

my example xml:

<?xml version="1.0" encoding="UTF-8"?>
<xml>
<level01>
<level02>
<level03>
<level04>
<node q="3,4,5,7,8" p="zen"/>
<node q="a,s,e,o,l" p="zen"/>
</level04>
</level03>
# >> here will be the new node, called <subi/> <<   
<level03>
<level04>
<node q="x,y" p="zen"/>
<node q="xxx,yyy" p="zen"/>
</level04>
</level03>
</level02>
</level01>
</xml>

The node is created like this:

subi = ETL.SubElement(root[0][0][1][0][0], 'subi')

which works, it can then be accessed via root001000 and it's tag can be read.

but I fail trying to add attributes.

I tried using the syntax I found in another thread here: (with my names ofc)

>>> myattributes = {"size": "small", "gender": "unknown"}
>>> child = ET.SubElement(parent, "child", attrib=myattributes, age="10" )

Also I tried it directly, like

subi = ETL.SubElement(root[0][0][1][0][0], 'subi', attrib={"size": "small", "gender": "unknown"})

Results are always

root[0][0][1][0][0][0].tag
'subi'

but

root[0][0][1][0][0][0].attrib
{}

I also found how lxml does it, but this does not work with elementtree

#Any keyword arguments of the form name=value that you supply to the constructor are added #to the element's attributes. For example, this code:

newReed = etree.Element('reed', pitch='440', id='a4')

#will produce an element that looks like this:

<reed pitch='440' id='a4'/>

What am I doing wrong? How can I do it right? Is there a way to make elementtree do it? Or do I have to use lxml? (which would be dispreferred) ?

like image 501
sibert Avatar asked Sep 12 '14 11:09

sibert


People also ask

How do you add an attribute to XML tag in Python?

The constructors for Element and SubElement include **extra , which accepts attributes as keyword arguments. This allows you to add an arbitrary number of attributes. You can also use use . set to add attributes to a pre-existing element.

How does Python handle XML?

To read an XML file using ElementTree, firstly, we import the ElementTree class found inside xml library, under the name ET (common convension). Then passed the filename of the xml file to the ElementTree. parse() method, to enable parsing of our xml file. Then got the root (parent tag) of our xml file using getroot().

How do you parse an XML string in Python?

3.2 Parsing an XML String We use the ElementTree. fromstring() method to parse an XML string. The method returns root Element directly: a subtle difference compared with the ElementTree. parse() method which returns an ElementTree object.

What is Etree in Python?

etree. ElementTree module implements a simple and efficient API for parsing and creating XML data. Changed in version 3.3: This module will use a fast implementation whenever available.


2 Answers

Isn't this you are trying to do? Assuming that subi is your element and you can access it, you can further use ElementTree method set:

subi.set(attr, value)

Look here about set method of ElementTree : https://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.Element.set

like image 109
German Petrov Avatar answered Sep 17 '22 04:09

German Petrov


You can specify attributes for an Element or SubElement during creation with keyword arguments.

import xml.etree.ElementTree as ET

root = ET.Element('Summary')
ET.SubElement(root, 'TextSummary', Status='Completed')
# <Summary><TextSummary Status="Completed" /></Summary>

Alternatively, you can use .set to add an attribute to an element after creation.

import xml.etree.ElementTree as ET

root = ET.Element('Summary')
sub = ET.SubElement(root, 'TextSummary')
sub.set('Status', 'Completed')
# <Summary><TextSummary Status="Completed" /></Summary>

Generated XML:

<Summary>
    <TextSummary Status="Completed"/>
</Summary>

Explanation:

The constructors for Element and SubElement include **extra, which accepts attributes as keyword arguments.

xml.etree.ElementTree.Element(tag, attrib={}, **extra)
xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)

This allows you to add an arbitrary number of attributes.

root = ET.Element('Summary', Date='2018/07/02', Timestamp='11:44am')
# <Summary Date = "2018/07/02" Timestamp = "11:44am">

You can also use use .set to add attributes to a pre-existing element. However, this can only add one element at a time. (Suggested by German Petrov).

root = ET.Element('Summary')
root.set('Date', '2018/07/02')
root.set('Timestamp', '11:44am')
# <Summary Date = "2018/07/02" Timestamp = "11:44am">

Full Example:

import xml.etree.ElementTree as ET

root = ET.Element('school', name='Willow Creek High')
ET.SubElement(root, 'student', name='Jane Doe', grade='9')
print(ET.tostring(root).decode())
# <school name="Willow Creek High"><student grade="9" name="Jane Doe" /></school>
like image 29
Stevoisiak Avatar answered Sep 19 '22 04:09

Stevoisiak