0

I seem to be stuck. I am trying to get multiple iterations of the xml that is generated from my python code. It only writes the latest iteration to file.

Here is my code:

import xml.etree.cElementTree as ET
from random import randint

i=5
while i>-4:
  event = ET.Element("event")
  event.set("class", "rer")
  event.set("id", "EV_%d" % (i))
  event.set("date", "${ev_d}")

  loc = ET.SubElement(event, "loc")
  flir = ET.SubElement(loc, "flir")

  de = ET.SubElement(flir, "de")
  de.set("dist", "km")
  de.set("val", "%d" % (randint(0,2)))

  i -=1   

  tree = ET.ElementTree(event)
  tree.write("test.xml")

What I get:

<event class="rer" date="${ev_d}" id="EV_-3">
  <loc>
    <flir>
      <de dist="km" val="0" />
    </flir>
  </loc>
</event>

What I want in the output file:

<event class="rer" date="${ev_d}" id="EV_5">
  <loc>
    <flir>
      <de dist="km" val="0" />
    </flir>
  </loc>
</event>
<event class="rer" date="${ev_d}" id="EV_4">
  <loc>
    <flir>
      <de dist="km" val="0" />
    </flir>
  </loc>
</event>
<event class="rer" date="${ev_d}" id="EV_3">
  <loc>
    <flir>
      <de dist="km" val="0" />
    </flir>
  </loc>
</event>

Thanks in advance for your help.

Regards, merit_2

6
  • Indent your code correctly please Commented Mar 15, 2016 at 16:14
  • Fixed indentation. Thanks. Commented Mar 15, 2016 at 16:26
  • 1
    What you want is invalid XML. An XML document must consist of a single element at the top level, not multiple elements. Commented Mar 15, 2016 at 16:27
  • 1. ElementTree.write does not append to a file. 2. What is the purpose of i? In your code it doesn't look like it ever gets updated, so this will just run forever.. Commented Mar 15, 2016 at 16:27
  • Sorry, I edited out my decrement statement. I see that I am not appending my file, but I don't understand how to do so. I know this is not well formatted xml, its a component of what I am trying to make. Commented Mar 15, 2016 at 16:32

2 Answers 2

1

As @jwodder pointed out, your proposed output is not valid XML. Your options are to fix that or get around it. Since you mentioned that this is only a component, here's a way to do it if you have a parent element that each <event> will be nested under.

import xml.etree.cElementTree as ET
from random import randint

parent = ET.Element("parent")
tree = ET.ElementTree(parent)

i=5
while i>-4:
    event = ET.Element("event")
    event.set("class", "rer")
    event.set("id", "EV_%d" % (i))
    event.set("date", "${ev_d}")

    loc = ET.SubElement(event, "loc")
    flir = ET.SubElement(loc, "flir")

    de = ET.SubElement(flir, "de")
    de.set("dist", "km")
    de.set("val", "%d" % (randint(0,2)))

    i -=1   

    parent.append(event)

tree.write("test.xml")

Here I added the parent element and append-ed event to the parent, then wrote the parent tree out to file at the end.

Output:

<parent>
  <event class="rer" date="${ev_d}" id="EV_5">
    <loc>
      <flir>
        <de dist="km" val="1" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_4">
    <loc>
      <flir>
        <de dist="km" val="2" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_3">
    <loc>
      <flir>
        <de dist="km" val="2" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_2">
    <loc>
      <flir>
        <de dist="km" val="1" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_1">
    <loc>
      <flir>
        <de dist="km" val="2" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_0">
    <loc>
      <flir>
        <de dist="km" val="0" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_-1">
    <loc>
      <flir>
        <de dist="km" val="2" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_-2">
    <loc>
      <flir>
        <de dist="km" val="0" />
      </flir>
    </loc>
  </event>
  <event class="rer" date="${ev_d}" id="EV_-3">
    <loc>
      <flir>
        <de dist="km" val="2" />
      </flir>
    </loc>
  </event>
</parent>
Sign up to request clarification or add additional context in comments.

1 Comment

Glad to hear it! Don't forget to upvote or accept helpful answers :)
1

You continually overwrite event in the while loop - so naturally you have just on event which gets printed. You need to do something like:

import xml.etree.cElementTree as ET
from random import randint

i = 5
events = []
while i > -4:
    event = ET.Element("event")
    event.set("class", "rer")
    event.set("id", "EV_%d" % (i))
    event.set("date", "${ev_d}")
    loc = ET.SubElement(event, "loc")
    flir = ET.SubElement(loc, "flir")
    de = ET.SubElement(flir, "de")
    de.set("dist", "km")
    de.set("val", "%d" % (randint(0, 2)))
    events.append(event)
    i -= 1

with open('output.xml', 'w') as out:
    for event in events:
        tree = ET.ElementTree(event)
        tree.write(out)
        out.write('\n')

1 Comment

Thanks. Works great.

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.