python-3.xxmlnested-lists

Iterating through lists to create XML nodes


I am parsing a large XML file to create 2 lists (channelName & channelNum), and the creation of these lists is working.
What I am trying to do next is create a new, smaller XML file based on the lists created, with a separate child node () for each set of channel names and channel numbers.

The lists created from the code below (shortened here) are:

channelName = ['Channel 01', 'Channel 02', 'Channel 03', 'FOX', 'NBC', 'Channel 04']
channelNum = ['1', '2', '3', '4', '5', '6']

The code I have tried is:

import xml.etree.ElementTree as ET

tree = ET.parse('svd_guide.xml')
root = tree.getroot()

ChannelName = []
ChannelNum = []

for child in root.findall('channel'):
    ChannelName.append(child.find('name').text)
    ChannelNum.append(child.find('logicalChannel').text)

def create_xml():
    channelroot = ET.Element("channels")
    child = ET.SubElement(channelroot, "channel")

    for name, num in zip(ChannelName, ChannelNum):
        ET.SubElement(child, "name").text = name
        ET.SubElement(child, "chan").text = num

    guidetree = ET.ElementTree(channelroot)

    guidetree.write("guide.xml", encoding = "utf-8", xml_declaration = True)    

create_xml()

The results I get are:

<?xml version='1.0' encoding='utf-8'?\>  
<channels>
    <channel>
        <name>Channel 01</name>
        <chan>1</chan>
        <name>Channel 02</name>
        <chan>2</chan>
        <name>Channel 03</name>
        <chan>3</chan>
        <name>FOX</name>
        <chan>4</chan>
        <name>NBC</name>
        <chan>5</chan>
        <name>Channel 04</name>
        <chan>6</chan>
   </channel>
</channels>

The results I was hoping to get are:

<?xml version='1.0' encoding='utf-8'?\>  
<channels>
    <channel>
        <name>Channel 01</name>
        <chan>1</chan>
    </channel>
    <channel>
        <name>Channel 02</name>
        <chan>2</chan>
    </channel>
    <channel>
        <name>Channel 03</name>
        <chan>3</chan>
    </channel>
    <channel>
        <name>FOX</name>
        <chan>4</chan>
    </channel>
    <channel>
        <name>NBC</name>
        <chan>5</chan>
    </channel>
    <channel>
        <name>Channel 04</name>
        <chan>6</chan>
   </channel>

Solution

  • You only need to move child = ET.SubElement(channelroot, "channel") to inside the for-loop, because you want/need to create a channel multiple times.

    I changed some other parts, because I do not have a svd_guide.xml, so I used an init on the ChannelName and ChannelNum.

    import xml.etree.ElementTree as ET
    
    #tree = ET.parse('svd_guide.xml')
    #root = tree.getroot()
    
    ChannelName = ['Channel 01', 'Channel 02', 'Channel 03', 'FOX', 'NBC', 'Channel 04']
    ChannelNum = ['1', '2', '3', '4', '5', '6']
    
    #for child in root.findall('channel'):
    #    ChannelName.append(child.find('name').text)
    #    ChannelNum.append(child.find('logicalChannel').text)
    
    def create_xml():
        channelroot = ET.Element("channels")
        #child = ET.SubElement(channelroot, "channel")
    
        for name, num in zip(ChannelName, ChannelNum):
            child = ET.SubElement(channelroot, "channel")
            ET.SubElement(child, "name").text = name
            ET.SubElement(child, "chan").text = num
            
    
        guidetree = ET.ElementTree(channelroot)
    
        guidetree.write("guide.xml", encoding = "utf-8", xml_declaration = True)    
    
    create_xml()
    

    output (guide.xml):

    <?xml version='1.0' encoding='utf-8'?>
    <channels>
        <channel/>
        <channel>
            <name>Channel 01</name>
            <chan>1</chan>
        </channel>
        <channel>
            <name>Channel 02</name>
            <chan>2</chan>
        </channel>
        <channel>
            <name>Channel 03</name>
            <chan>3</chan>
        </channel>
        <channel>
            <name>FOX</name>
            <chan>4</chan>
        </channel>
        <channel>
            <name>NBC</name>
            <chan>5</chan>
        </channel>
        <channel>
            <name>Channel 04</name>
            <chan>6</chan>
        </channel>
    </channels>