1

I want to create subelement to an element that comes next to the element country singapore here.

Suppose my test.xml file looks like this

<?xml version="1.0" encoding="UTF-8"?>

<data>
    <country name="Malaysia" tst="bh">
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Singapore" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <district>
        <A name="test">
        </A>
    </district>
    <country name="Singapore" tst="ab">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
   <district>
        <B name="test">
        </B>
    </district>
</data>

In the above example,I want to create subelement to element district but the element present above should be country "singapore". It should be

<district>
   <t1 name="t1>
   </t1>
     <B name="test">
    </B>
</district>

import xml.etree.ElementTree as et


tree = et.parse("test.xml")
root = tree.getroot()

country = root.find(".//country[@name='Singapore']")

et.subelement(country,"add new subelement")

I am able to add subelement to country element. But i couldn't take the district element below the country "singapore".

Can anyone please help me here??

Minnie
  • 51
  • 7

2 Answers2

1

Here is how it can be done with ElementTree.

import xml.etree.ElementTree as ET

root = ET.parse("country.xml").getroot()

# A list of all children of the root element (in document order)
children = list(root)

# Find the Singapore 'country' element
sing = root.find(".//country/[@name='Singapore']")

# Get the index of the 'country' element 
ix = children.index(sing)

# Find the wanted 'district' sibling element (position ix+1 in the list)
district = children[ix+1]

# Create a new 't1' element and add to 'district'
t1 = ET.Element("t1", name="t1")
district.insert(0, t1)

print(ET.tostring(root).decode("UTF-8"))

Output:

<data>
    <country name="Malaysia" tst="bh">
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Singapore" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <district>
        <A name="test">
        </A>
    </district>
    <country name="Singapore" tst="ab">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
   <district>
        <t1 name="t1" /><B name="test">        <!-- New element added here --> 
        </B>
    </district>
</data>
mzjn
  • 48,958
  • 13
  • 128
  • 248
  • With [lxml](http://lxml.de), the wanted `district` element can be directly located using XPath: `district = root.xpath(".//district[preceding-sibling::country[1][@name='Singapore']]")[0]`. – mzjn Aug 13 '18 at 11:12
0

What you are trying to attempt is not possible, as no below or above exists in XML. The data in XML is unordered. If you want to create a relation between country and district, you can ether add a Country Attribute to the District Element:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <country name="Malaysia" tst="bh">
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Singapore" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <district country="Malaysia">
        <A name="test">
        </A>
    </district>
    <country name="Singapore" tst="ab">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
   <district country="Singaporse">
        <B name="test">
        </B>
    </district>
</data>


import xml.etree.ElementTree as et    
tree = et.parse("test.xml")
root = tree.getroot()    
district = root.find(".//district[@country='Singapore']")    
et.subelement(district,"add new subelement")

Or make the district element a child of the country element:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <country name="Malaysia" tst="bh">
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Singapore" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
        <district>
            <A name="test"/>
        </district>
    </country>
    <country name="Singapore" tst="ab">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
        <district country="Singaporse">
            <B name="test"/>
        </district>
    </country>
</data>


import xml.etree.ElementTree as et    
tree = et.parse("test.xml")
root = tree.getroot()    
district = root.find(".//country[@name='Singapore']/district")    
et.subelement(district,"add new subelement")

Edit: added python code

wat
  • 32
  • 5
  • I think it is misleading to say that "the data in XML is unordered". The order of elements can be very important. See https://stackoverflow.com/q/1131495/407651. – mzjn Aug 01 '18 at 09:03
  • that is just an example i have given. my scenario is based on country and district. I have valid elements. Instead of country lets say i have A element and B element instead of district. How to achieve this? – Minnie Aug 01 '18 at 10:29