Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create nested dictionary from XML using python?

I am reading an XML file and take part of it and write it to YAML file. For example, in this xml file,

<project>


  <scm class="hudson.scm.NullSCM"/>
  <assignedNode>python</assignedNode>
  <canRoam>false</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>
    <hudson.triggers.TimerTrigger>
      <spec>H * * * *</spec>
    </hudson.triggers.TimerTrigger>
  </triggers>
  <concurrentBuild>false</concurrentBuild>
  <builders>

I want to read only the disabled value and the spec value and write it to a YAML file like this: Expected output:

disabled: 'false'
name: Cancellation_CMT_Tickets
triggers:
  hudson.triggers.TimerTrigger:
    spec: H * * * *

Only when my resultant dictionary is in this format

d = {"trigger":{"hudson.triggers.TimerTrigger": {"spec": "H * * * *"}}}

I can dump that into yaml file with the above format. MY current code looks like this, search key is passed as runtime arguments

import os, xml.etree.ElementTree as ET
import yaml,sys
tree = ET.parse('test.xml')
root = tree.getroot()

d = {}
def xmpparse(root,searchkey):
    for child in root:
        if child.tag == searchkey:
            d[child.tag]=child.text
        elif len(child):
           xmpparse(child,searchkey)
for i in sys.argv:
    xmpparse(root,i)

print(yaml.dump(d, default_flow_style=False))

Current output:

disabled: 'false'
spec: H * * * *

Any help would be much appreciated. Thanks in advance!

like image 296
Jayabalan Bala Avatar asked Feb 13 '26 04:02

Jayabalan Bala


1 Answers

I believe this should take care of the nested dictionary problem, at least; it's based on various answers on SO on how to form nested dictionaries (and there may be other methods):

    import lxml.html as LH

    class NestedDict(dict):
        def __missing__(self, key):
              self[key] = NestedDict()
              return self[key]

    data =     [your xml above]

    doc = LH.fromstring(data)

    for i in doc:
           if i.tag == 'triggers':
                for child in i.getchildren():
                    d = NestedDict()
                    d[i.tag][child.tag][child[0].tag] = i.text_content().strip()

    print(d)

Output:

{'triggers': {'hudson.triggers.timertrigger': {'spec': 'H * * * *'}}}

like image 79
Jack Fleeting Avatar answered Feb 17 '26 04:02

Jack Fleeting



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!