I am writing a function to generate an xml header for a number of various requests using ElementTree and Python 3.x:
import xml.etree.ElementTree as ET
def xml():
Message = ET.Element('Message')
Header = ET.SubElement(Message, 'Header')
Endpoint = ET.SubElement(Header, 'Endpoint')
endpoint_id = ET.SubElement(Endpoint, 'ID', value='APP')
Context = ET.SubElement(Header, 'Context', id='request')
Itinerary = ET.SubElement(Header, 'Itinerary')
endpoint_uri = ET.SubElement(Itinerary, 'Endpoint' uri='/blah/blah/common/xml')
header = ET.tostring(Message)
Which generates the following output (formatted to make it easier to read):
<Message>
<Header>
<Endpoint>
<ID value="APP"/>
</Endpoint>
<Context id="request"/>
<Itinerary>
<Endpoint uri="/blah/blah/common/xml"/>
</Itinerary>
</Header>
</Message>
I am trying to insert the following XML into it above the "Message" Element:
header = xml()
Body = ET.Element('Body')
Account = ET.SubElement(Body, 'Account', operation='query')
id_value = ET.SubElement(Account, 'ID', ns='FOO', value='123456789')
body = ET.tostring(Body)
header.insert(body,'Message')
So it will end up like this:
<Message>
<Header>
<Endpoint>
<ID value="APP"/>
</Endpoint>
<Context id="request"/>
<Itinerary>
<Endpoint uri="/blah/blah/common/xml"/>
</Itinerary>
</Header>
<Body>
<Account operation="query">
<ID ns="FOO" value="123456789"/>
</Account>
</Body>
</Message>
Everything I have come across to do this using .insert() uses an example of XML from a file, which won't work as the XML doc is clearly being generated as part of the script. The script fails
AttributeError: 'NoneType' object has no attribute 'insert'
And attempts to run getroot() on the header value fail because it is expecting a text file and not generated XML.
CodePudding user response:
Figured it out:
import xml.etree.ElementTree as ET
import xml.dom.minidom
def xml():
Message = ET.Element('Message')
Header = ET.SubElement(Message, 'Header')
Endpoint = ET.SubElement(Header, 'Endpoint')
endpoint_id = ET.SubElement(Endpoint, 'ID', value='APP')
Context = ET.SubElement(Header, 'Context', id='request')
Itinerary = ET.SubElement(Header, 'Itinerary')
endpoint_uri = ET.SubElement(Itinerary, 'Endpoint' uri='/blah/blah/common/xml')
return Message
header = xml()
Body = ET.Element('Body')
Account = ET.SubElement(Body, 'Account', operation='query')
id_value = ET.SubElement(Account, 'ID', ns='FOO', value='123456789')
header.insert(1,Body)
header = ET.tostring(header)
doc = xml.dom.minidom.parseString(header).toprettyxml(indent=" ")
print(doc)
Which produces:
<Message>
<Header>
<Endpoint>
<ID value="APP"/>
</Endpoint>
<Context id="request"/>
<Itinerary>
<Endpoint uri="/blah/blah/common/xml"/>
</Itinerary>
</Header>
<Body>
<Account operation="query">
<ID ns="FOO" value="123456789"/>
</Account>
</Body>
</Message>
H/T to Jack Fleeting for the insert method catch.
CodePudding user response:
Try changing
header.insert(body,'Message')
to
Message.insert(1,Body)
and see if it works.