Search code examples
pythonlxml

Pass root element as a variable


I have a python function that takes a partial xml string and a root element tag and tries to construct a valid xml. I am having trouble getting this to work.

from lxml import etree
from lxml.builder import E


try:
    root_element = 'TagStatus'
    partial_xml_contents = """<Header>
    <SubmissionType>TVL</SubmissionType>
    <SubmissionDateTime>2019-12-19T09:20:25Z</SubmissionDateTime>
    <SSIOPHubID>9001</SSIOPHubID>
  </Header>
  <Details>
      <RecordType>TB01</RecordType>
      <Status>V</Status>
      <PassInfo>
        <PassType>4</PassType>
        <PassStartDateTime>2019-12-19T08:30:00Z</PassStartDateTime>
        <PassEndDateTime>2019-12-19T18:29:59Z</PassEndDateTime>
      </PassInfo>
      <Class>01</Class>
      <SubDetails>
        <Country>US</Country>
        <State>DE</State>
        <Number>00003</Number>
      </SubDetails>
      <AccountDetails>
        <AccountNumber>123</AccountNumber>
      </AccountDetails>
    </Details>
"""
    print('root_element: %s' % str(root_element))
    print('partial_contents: %s' % str(partial_xml_contents))
    partial_xml_contents = partial_xml_contents.replace('\n', '')
    retString =  etree.tostring(E(str(root_element), E(str(partial_xml_contents)) ))
    print(retString)
except Exception as e:
    print(str(e))

I'm getting an error: Invalid tag name and the partial contents listed. From my understanding, lxml builder allows for a valid xml to be built using partial chunks.

Edit: Please see the below link. The OP has multiple xml chunks(fully formed). In my case, my xml is partial.

Append xml to xml using python.I have two xml files which i need to merge .so is there anyway i can merge both files


Solution

  • lxml's E factory can take a tag name as argument, but not a whole XML document. The following much smaller (and well-formed) example also results in a "Invalid tag name" error: E("<tag>x</tag>").

    Here is how you can create a well-formed XML document:

    from lxml import etree
     
    root_element = 'TagStatus'     
    
    partial_xml_contents = """
    <Header>
    </Header>
    <Details>
    </Details>"""
     
    # Add the root element using an f-string
    well_formed_xml_contents = f"<{root_element}>{partial_xml_contents}</{root_element}>"
     
    # Verify that there are no errors
    root = etree.fromstring(well_formed_xml_contents)