0

I am trying to build an xml from python, how to loop in the sub elements? I have been trying to get it in the format needed but cannot figure out how

The output I am getting is this:

b'<member x0="28.921" y0="710.377" text="1. Case gdfh "><sub/></member>'
b'<member><sub x0="54.721" y0="695.792" text="Version "> 0</sub></member>'
b'<member><sub x0="54.721" y0="688.112" text="AER Number "> 4735986</sub></member>'
b'<member><sub x0="54.721" y0="680.792" text="Initial Unit "> SBFBKJSF</sub></member>'
b'<member x0="28.921" y0="561.937" text="2. Patient"><sub/></member>'
b'<member><sub x0="54.721" y0="510.697" text="Patient Information"></sub></member>'
b'<member><sub x0="54.721" y0="496.112" text="Age "> 60 Years</sub></member>'
b'<member><sub x0="54.721" y0="488.432" text="Height "> 171 Centimeter</sub></member>'

The output I want is this:

b'
<member x0="28.921" y0="710.377" text="1. Case gdfh ">
    <sub x0="54.721" y0="695.792" text="Version "> 0</sub>
    <sub x0="54.721" y0="688.112" text="AER Number "> 4735986</sub>
    <sub x0="54.721" y0="680.792" text="Initial Unit "> SBFBKJSF</sub>
</member>
<member x0="28.921" y0="561.937" text="2. Patient">
    <sub x0="54.721" y0="510.697" text="Patient Information"></sub>
    <sub x0="54.721" y0="496.112" text="Age "> 60 Years</sub>
    <sub x0="54.721" y0="488.432" text="Height "> 171 Centimeter</sub>
</member>
'

The code I'm writing is this:

Here, 'st' is the list of objects

from lxml import etree
import xml.etree.ElementTree as xml


root = etree.Element('root')

for j in st:
    member = etree.SubElement(root, 'member')
    submbr = etree.SubElement(member, 'sub')

    if j.x0 == '28.921':
        root.append(member)
        member.append(submbr)
        member.attrib['x0'] = j.x0
        member.attrib['y0'] = j.y0
        member.attrib['text'] = j.text[0]
        member.text = j.text[1]
    else:
        submbr.attrib['x0'] = j.x0
        submbr.attrib['y0'] = j.y0
        submbr.attrib['text'] = j.text[0]
        submbr.text = j.text[1]



    out = etree.tostring(member)
    print(out)

The data structure , the st list when looped through has these values

TEXT                   x0       y0 
['1. Case gdfh ', ''] 28.921 , 710.377
['Version ', ' 0', ''] 54.721 , 695.792
['AER Number ', ' 4735986', ''] 54.721 , 688.112
['Initial Unit ', 'SBFBKJSF ', ''] 54.721 , 680.792
['2. Patient', ''] 28.921 , 561.937
['Patient Information', ''] 54.721 , 510.697
['Age ', ' 60 Years', ''] 54.721 , 496.112
['Height ', ' 171 Centimeter', ''] 54.721 , 488.432
4
  • Please also include the data structure that matches your sample (the st variable, but only the necessary part), so people don't have to make that up in order to provide tested code in an answer. Commented Feb 23, 2020 at 13:42
  • That being said, your if: body and your else: are equal. There is no need to have an if/else when you do the same thing in either case anyway. Commented Feb 23, 2020 at 13:44
  • Without else: , it gives a different output, doesnt includes the values of submember Commented Feb 23, 2020 at 13:54
  • 1
    Ahh, seeing the input data makes it much easier to understand. Commented Feb 23, 2020 at 14:09

1 Answer 1

1

You want a new member every time the value of x0 equals '28.921', and in any other case you want to add a sub-member to whatever the current member is - unless there is no current member, which can happen when the first item in st is not x0 == '28.921'.

from lxml import etree

class betterdict(dict):
    def __getattr__(self, key):
        return self.get(key)

st = [
    betterdict({'text': ['1. Case gdfh ', ''],              'x0': '28.921', 'y0': '710.377'}),
    betterdict({'text': ['Version ', ' 0', ''],             'x0': '54.721', 'y0': '695.792'}),
    betterdict({'text': ['AER Number ', ' 4735986', ''],    'x0': '54.721', 'y0': '688.112'}),
    betterdict({'text': ['Initial Unit ', 'SBFBKJSF ', ''], 'x0': '54.721', 'y0': '680.792'}),
    betterdict({'text': ['2. Patient', ''],                 'x0': '28.921', 'y0': '561.937'}),
    betterdict({'text': ['Patient Information', ''],        'x0': '54.721', 'y0': '510.697'}),
    betterdict({'text': ['Age ', ' 60 Years', ''],          'x0': '54.721', 'y0': '496.112'}),
    betterdict({'text': ['Height ', ' 171 Centimeter', ''], 'x0': '54.721', 'y0': '488.432'}),
]

root = etree.Element('root')
member = None

for j in st:
    if j.x0 == '28.921':
        member = etree.SubElement(root, 'member')
        member.attrib['x0'] = j.x0
        member.attrib['y0'] = j.y0
        member.attrib['text'] = j.text[0]
    elif member is not None:
        submbr = etree.SubElement(member, 'sub')
        submbr.attrib['x0'] = j.x0
        submbr.attrib['y0'] = j.y0
        submbr.attrib['text'] = j.text[0]
        submbr.text = j.text[1]

out = etree.tostring(root)
print(out)

prints exactly what you want (formatted for readability)

<root>
  <member x0="28.921" y0="710.377" text="1. Case gdfh ">
    <sub x0="54.721" y0="695.792" text="Version "> 0</sub>
    <sub x0="54.721" y0="688.112" text="AER Number "> 4735986</sub>
    <sub x0="54.721" y0="680.792" text="Initial Unit ">SBFBKJSF </sub>
  </member>
  <member x0="28.921" y0="561.937" text="2. Patient">
    <sub x0="54.721" y0="510.697" text="Patient Information"></sub>
    <sub x0="54.721" y0="496.112" text="Age "> 60 Years</sub>
    <sub x0="54.721" y0="488.432" text="Height "> 171 Centimeter</sub>
  </member>
</root>
Sign up to request clarification or add additional context in comments.

7 Comments

Yes, that is what I want, but the above code doesn't work., tried it
@user12637176 The update to your question showed how your input data is shaped. It does not show your input data (i.e. it's not Python code that I could run to get the same data structure you have). For example '28.921' will never be equal to 28.921. The one is a string, the other is a number. Your data looks like it has numbers. Your code sample treats it as a string. Which of it is it? Again, there is no way for me to post tested code when you don't supply actual input to test on.
@user12637176 So I have made up a data structure that might or might not be what you have, but it shows that the code definitely works.
Yes..it is a string , i match the string and the data is in list form not dictionary, as the data is repetitive, i cannot use dictionary
@user12637176 I've shown you a solution that works. The rest is up to you.
|

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.