5

I have a existing xml file as following:

<vehicleTravelTimeMeasurements>
        <vehicleTravelTimeMeasurement name="ckkkkkkkkkk" no="2">
            <start link="1" pos="3.864983"/>
            <end link="3" pos="23.275375"/>
        </vehicleTravelTimeMeasurement>
        <vehicleTravelTimeMeasurement name="" no="3">
            <start link="1" pos="3.864983"/>
            <end link="2" pos="13.275375"/>
        </vehicleTravelTimeMeasurement>
</vehicleTravelTimeMeasurements>

I am trying to construct the same format as shown above by using xml.etree.cElementTree, and add them into the xml correctly:

new = ET.Element("vehicleTravelTimeMeasurement", name = "kkk", no = "4")
newsub1 =  ET.Element("start", link = "1", pos="3.88888")
newsub2 = ET.Element("end",link = "3", pos = "3.88888")

could someone help me out with this?

Thank you in advance!

1
  • Use new.append(newsub1). Commented Dec 31, 2015 at 17:09

2 Answers 2

6

You wanted to use SubElement and add the start and end elements to the vehicleTravelTimeMeasurement element. Then insert that newly created element at position 2, since 0 and 1 are already occupied.

import xml.etree.ElementTree as ET

def indent(elem, level=0):
    i = "\n" + level*"  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for elem in elem:
            indent(elem, level+1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i

xml = '''<vehicleTravelTimeMeasurements>
        <vehicleTravelTimeMeasurement name="ckkkkkkkkkk" no="2">
            <start link="1" pos="3.864983"/>
            <end link="3" pos="23.275375"/>
        </vehicleTravelTimeMeasurement>
        <vehicleTravelTimeMeasurement name="" no="3">
            <start link="1" pos="3.864983"/>
            <end link="2" pos="13.275375"/>
        </vehicleTravelTimeMeasurement>
</vehicleTravelTimeMeasurements>'''

root = ET.fromstring(xml)
new = ET.Element("vehicleTravelTimeMeasurement", name = "kkk", no = "4")
newsub1 = ET.SubElement(new, "start", link = "1", pos="3.88888")
newsub2 = ET.SubElement(new, "end",link = "3", pos = "3.88888")
root.insert(2, new)
indent(root)
with open('test.xml', 'w') as f:
    f.write(ET.tostring(root))
Sign up to request clarification or add additional context in comments.

3 Comments

yes. you right. they are same. but my question is when I open the file as xml. the new added elements are not shown structured as the original [0] or [1] element.
@Condo_programmer my latest edit writes to a file now
thank you so much! never mind. it's about notepad ++ issue. the problem sovled
0

Short version / Updates & Edits:

The only thing you need to do is (A) add newsub1 and newsub2 to new. And (B) add new to root.

root = ET.fromstring(xml)  # or whichever way you're getting `root`
# these 3 lines form your code:
new = ET.Element('vehicleTravelTimeMeasurement', name="kkk", no="4")
newsub1 = ET.Element('start', link='1', pos='3.88888')
newsub2 = ET.Element('end', link='3', pos='3.88888')
# the next steps to add
new.append(newsub1)
new.append(newsub2)
root.append(new)

Note that (A) & (B) can be done in any order and this can be shortened, as below:

>>> root = ET.fromstring(xml)
>>> new = ET.Element('vehicleTravelTimeMeasurement', name="kkk", no="4")
>>> root.append(new)  # note that I've immediately added `new`
>>> ET.SubElement(new, 'start', link='1', pos='3.88888')
<Element 'start' at 0x24707b8>
>>> ET.SubElement(new, 'end', link='3', pos='3.88888')
<Element 'end' at 0x24ea978>
>>> # there's no need to store the subelements in `newsub1` and
... # `newsub2` if you don't need to do anything with them
...
>>> indent(root)
>>> print ET.tostring(root)
<vehicleTravelTimeMeasurements>
  <vehicleTravelTimeMeasurement name="ckkkkkkkkkk" no="2">
    <start link="1" pos="3.864983" />
    <end link="3" pos="23.275375" />
  </vehicleTravelTimeMeasurement>
  <vehicleTravelTimeMeasurement name="" no="3">
    <start link="1" pos="3.864983" />
    <end link="2" pos="13.275375" />
  </vehicleTravelTimeMeasurement>
  <vehicleTravelTimeMeasurement name="kkk" no="4">
    <start link="1" pos="3.88888" />
    <end link="3" pos="3.88888" />
  </vehicleTravelTimeMeasurement>
</vehicleTravelTimeMeasurements>

Notes:

  1. I've added new to root just after creating it.
  2. Use append instead of insert if you know you're always appending, instead of needing to keep track of the no's in your original xml
    • unless you need to read that anyway to calculate the next 'no' attribute
  3. ET.SubElement(new) updates new (and root) even though new has already been appended.
  4. There's no need to store the subelements in newsub1 and newsub2 if you don't need to do anything with them.
    • First method (like yours) creates the elements and then adds them to root or new.
    • Second method uses ET.SubElement(new, ...) to add the elements to its parent.
  5. The function indent is from here, which quotes this source.

Re # 4.2 above, could also be done as:

root = ET.fromstring(xml)
new = ET.SubElement(root, 'vehicleTravelTimeMeasurement', name="kkk", no="4")
# `new` is already created as a subelement of `root` and appended
ET.SubElement(new, 'start', link='1', pos='3.88888')
ET.SubElement(new, 'end', link='3', pos='3.88888')

From the Subelement docs:

This function creates an element instance, and appends it to an existing element.

(emphasis mine)

2 Comments

Hi, thank you for the answer. could you please be more specific?
There was no add_element, I was thinking of ET.SubElement(<parent>, ...). So that part of my answer was totally wrong. Also, the last code snippet in the edited answer is the smallest change you'd need to make to do what you wanted. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.