1

I have the following XML structure and I want to add a new node if it does not exist at a specific location.

<root>
    <OuterLevel>
        <Node>
            <Name>NodeA</Name>
        </Node>
        <Node>
            <Name>NodeB</Name>
        <Node>
        <SpecialNode>
            <Name>NodeZ</Name>
        </SpecialNode>
    </OuterLevel>
 </root>

I wrote a python script using element tree. http://docs.python.org/library/xml.etree.elementtree.html

import xml.etree.ElementTree as ET
tree = ET.parse('sampleFile.xml')
root = tree.getroot()
newNodeStr = 'NewNode'

if root[0][0].tag != newNodeStr :
    print('Now we add it')
    newNode = ET.Element(newNodeStr)
    newNodeName = ET.Element('Name')
    newNodeName.text = 'NodeC'
    newNode.append(newNodeName)
    root[0].insert(0, newNode)

tree.write('sampleFileNew.xml')

I wanted the XML structure to look like this:

<root>
    <OuterLevel>
        <NewNode>
            <Name>NodeC</Name>
        </NewNode>
        <Node>
            <Name>NodeA</Name>
        </Node>
        <Node>
            <Name>NodeB</Name>
        <Node>
        <SpecialNode>
            <Name>NodeZ</Name>
        </SpecialNode>
    </OuterLevel>
 </root>

But instead, it looks like this:

<root>
    <OuterLevel>
        <NewNode><Name>NodeC</Name></NewNode><Node>
            <Name>NodeA</Name>
        </Node>
        <Node>
            <Name>NodeB</Name>
        <Node>
        <SpecialNode>
            <Name>NodeZ</Name>
        </SpecialNode>
    </OuterLevel>
 </root>

I used the insert() method from element tree because I thought it would give me what I needed, which is inserting a node at a specific location. However, it looks like the insert() doesn't actually care about what is already in that position in the tree structure. Is there a method that I can use to fix the ordering? Is there a better way of doing this?

SpartaSixZero
  • 2,183
  • 5
  • 27
  • 46
  • 5
    Your examples are the same apart from indentation. There is no different ordering here. If you just want the indentation right, that's a matter of [pretty printing](http://stackoverflow.com/a/1206856/722121). – Gareth Latty Oct 12 '12 at 18:49

3 Answers3

2

syntactically those two outputs are the same, tree.write() might print your output the way you want it if you save the file and then re-parse it although I am not sure.

Jay
  • 303
  • 1
  • 3
1

Try this one it will pretty print the output as you want.

    try:
        reparsed = mini.parseString(mini.parse('YOUR_FILE_NAME').toxml())
        pretty_string =  '\n'.join([line for line in reparsed.toprettyxml(indent=' '*4).split('\n') if line.strip()])

        f = open('YOUR_FILE_NAME', 'w') 
        f.write(pretty_string) 
    finally:
        f.close()
1

It looks like you may need to use the pretty_print = True when you're rewriting the tree to the file. Perhaps you're parsing it in it's previous pretty_print form but the insert() does not add your new node in pretty_print form.

If you're not using LXML i'm not sure if this is possible, but try just changing the print to:

tree.write('sampleFileNew.xml', pretty_print = True)

Again, you may need to import lxml to use this functionality. Hope this helps.

Dave Smith
  • 11
  • 1