Search code examples
pythonxmlnamespaceselementtree

using Element Tree to edit the XML file with existing namespaces - I end up having new foreign namespaces created that I do not know, want and need


I have an XML file that I am parsing and editing(by adding nodes)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="ns" xmlns:ns1="ns1">
<soapenv:Body>
    <ns:CreateUpdateCustomer>
        <ns:Request>
            <ns:CustomerGroupReference referenceId="1">
                <ns1:CompanyInfo>
                    <ns1:ExternalCompanyID>111</ns1:ExternalCompanyID>
                </ns1:CompanyInfo>
                <ns1:CustomerGroupName>1111</ns1:CustomerGroupName>
            </ns:CustomerGroupReference>
            <ns:Customer>
                <ns1:CustomerReference referenceId="1">
                    <ns1:CustomerNumber>2222</ns1:CustomerNumber>
                </ns1:CustomerReference>
                <ns1:Detail>
                    <ns1:CustomerName>Name1</ns1:CustomerName>
                    <ns1:CustomerNumber>Number1</ns1:CustomerNumber>
                    <ns1:Country>CountryName</ns1:Country>
                    <ns1:Address1>Address1</ns1:Address1>
                    <ns1:Address2>Address2</ns1:Address2>
                    <ns1:Region>Region</ns1:Region>
                    <ns1:City>City</ns1:City>
                    <ns1:ZipCode>ZipCode</ns1:ZipCode>
                    <ns1:ContactName>ContactName</ns1:ContactName>
                    <ns1:ContactEmail>ContactEmail</ns1:ContactEmail>
                    <ns1:ContactPhone>ContactPhone</ns1:ContactPhone>
                </ns1:Detail>
            </ns:Customer>
        </ns:Request>
    </ns:CreateUpdateCustomer>
</soapenv:Body></soapenv:Envelope>

I use code below to populate the file

import xml.etree.ElementTree as ET
import pandas as pd

tree = ET.parse(r'Customer Request.xml')

root = tree.getroot()

dfXL = Alteryx.read("#1")


namespaces = {'ns1':'ns1',
                    'ns':'ns'}

print('Below we are parsing through all of the template nodes')


for item in root:
    if 'Body' in item.tag:
        for CreateUpdateCustomer in item:
            namespace = namespaces['ns']
            tagRequestName = '{' + '' + namespace + '}Request'
            for CustGroupRefId in dfXL['CustomerGroupReference referenceId'].unique().tolist():
                RequestElement = ET.Element(tagRequestName)
                dfCustGroup  = dfXL[dfXL['CustomerGroupReference referenceId'] == CustGroupRefId] 
                namespace = namespaces['ns']
                tagCustomerGroupReferenceName = '{' + '' + namespace + '}CustomerGroupReference'
                CustomerGroupReferenceElement = ET.Element(tagCustomerGroupReferenceName)
                CustomerGroupReferenceElement.set('referenceId',str(int(CustGroupRefId)))
                
                namespace = namespaces['ns1']
                tagCompanyInfoName = '{' + '' + namespace + '}CompanyInfo'

                CompanyInfoElement = ET.Element(tagCompanyInfoName)
                
                namespace = namespaces['ns1']
                tagExternalCompanyIDName = '{' + '' + namespace + '}ExternalCompanyID'

                ExternalCompanyIDElement = ET.Element(tagExternalCompanyIDName)

                firstOfTheList = dfCustGroup['ExternalCompanyID'].unique().tolist()

                ExternalCompanyIDElement.text = firstOfTheList[0]
                    
                CompanyInfoElement.append(ExternalCompanyIDElement)

                namespace = namespaces['ns1']
                tagCustomerGroupNameName = '{' + '' + namespace + '}CustomerGroupName'

                CustomerGroupNameElement = ET.Element(tagCustomerGroupNameName)
                firstOfTheList = dfCustGroup['CustomerGroupName'].unique().tolist()

                CustomerGroupNameElement.text = firstOfTheList[0]
                    
                CustomerGroupReferenceElement.append(CompanyInfoElement)

                CustomerGroupReferenceElement.append(CustomerGroupNameElement)
                
                RequestElement.append(CustomerGroupReferenceElement)
                
                for CustomerReferenceId in dfCustGroup['CustomerReference referenceId'].unique().tolist():
                    for index, row in dfCustGroup.iterrows():
                        if CustomerReferenceId == row['CustomerReference referenceId']:
                            namespace = namespaces['ns']
                            tagCustomerName = '{' + '' + namespace + '}Customer'

                            CustomerElement = ET.Element(tagCustomerName)

                            namespace = namespaces['ns1']
                            tagCustomerReferenceName = '{' + '' + namespace + '}CustomerReference'

                            CustomerReferenceElement = ET.Element(tagCustomerReferenceName)
                            CustomerReferenceElement.set('referenceId',str(int(CustomerReferenceId)))
                            
                            namespace = namespaces['ns1']
                            tagCustomerNumberName = '{' + '' + namespace + '}CustomerNumber'

                            CustomerNumberElement = ET.Element(tagCustomerNumberName)
                            CustomerNumberElement.text = str(row['CustomerNumber'])
                            
                            CustomerReferenceElement.append(CustomerNumberElement)

                            CustomerElement.append(CustomerReferenceElement)

                            namespace = namespaces['ns1']
                            tagDetailName = '{' + '' + namespace + '}Detail'

                            DetailElement = ET.Element(tagDetailName)

                            namespace = namespaces['ns1']
                            tagCustomerNameName = '{' + '' + namespace + '}CustomerName'

                            CustomerNameElement = ET.Element(tagCustomerNameName)
                            CustomerNameElement.text = str(row['CustomerName'])

                            DetailElement.append(CustomerNameElement)
                            
                            namespace = namespaces['ns1']
                            tagCustomerNumberName = '{' + '' + namespace + '}CustomerNumber'

                            CustomerNumberElement = ET.Element(tagCustomerNumberName)
                            CustomerNumberElement.text = str(row['CustomerNumber'])

                            DetailElement.append(CustomerNumberElement)
                            
                            namespace = namespaces['ns1']
                            tagCountryName = '{' + '' + namespace + '}Country'

                            CountryElement = ET.Element(tagCountryName)
                            CountryElement.text = str(row['Country'])

                            DetailElement.append(CountryElement)
                            
                            namespace = namespaces['ns1']
                            tagAddress1Name = '{' + '' + namespace + '}Address1'

                            Address1Element = ET.Element(tagAddress1Name)
                            Address1Element.text = str(row['Address1'])

                            DetailElement.append(Address1Element)
                            
                            namespace = namespaces['ns1']
                            tagAddress2Name = '{' + '' + namespace + '}Address2'

                            Address2Element = ET.Element(tagAddress2Name)
                            Address2Element.text = str(row['Address2'])

                            DetailElement.append(Address2Element)
                            
                            namespace = namespaces['ns1']
                            tagRegionName = '{' + '' + namespace + '}Region'

                            RegionElement = ET.Element(tagRegionName)
                            RegionElement.text = str(row['Region'])

                            DetailElement.append(RegionElement)
                            
                            namespace = namespaces['ns1']
                            tagCityName = '{' + '' + namespace + '}City'

                            CityElement = ET.Element(tagCityName)
                            CityElement.text = str(row['City'])

                            DetailElement.append(CityElement)
                            
                            namespace = namespaces['ns1']
                            tagZipCodeName = '{' + '' + namespace + '}ZipCode'

                            ZipCodeElement = ET.Element(tagZipCodeName)
                            ZipCodeElement.text = str(row['ZipCode'])
 
                            DetailElement.append(ZipCodeElement)
                            
                            namespace = namespaces['ns1']
                            tagContactNameName = '{' + '' + namespace + '}ContactName'

                            ContactNameElement = ET.Element(tagContactNameName)
                            ContactNameElement.text = str(row['ContactName'])

                            DetailElement.append(ContactNameElement)
                            
                            namespace = namespaces['ns1']
                            tagContactEmailName = '{' + '' + namespace + '}ContactEmail'

                            ContactEmailElement = ET.Element(tagContactEmailName)
                            ContactEmailElement.text = str(row['ContactEmail'])

                            DetailElement.append(ContactEmailElement)
                            
                            namespace = namespaces['ns1']
                            tagContactPhoneName = '{' + '' + namespace + '}ContactPhone'

                            ContactPhoneElement = ET.Element(tagContactPhoneName)
                            ContactPhoneElement.text = str(row['ContactPhone'])

                            DetailElement.append(ContactPhoneElement)
                            
                            CustomerElement.append(DetailElement)

                            RequestElement.append(CustomerElement)

                CreateUpdateCustomer.append(RequestElement)

tree = ET.ElementTree(root)

with open(r'Customer.xml', 'w') as f:
    tree.write(f, encoding='unicode')

File ends up being populated correctly , however, my namespaces in the new file are wrong, scrambled and offset. Plus I get 2 new namespaces as per example below:

Resulting fraction of the file is below - my issue is the orginal namespaces are renamed (ns and ns1) plus several new namespaces are created

<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns3="ns1" xmlns:ns4="ns">
    <ns0:Body>
        <ns3:CreateUpdateCustomer>
        <ns3:Request>
            <ns3:CustomerGroupReference referenceId="1">
            <ns4:CompanyInfo>
                <ns4:ExternalCompanyID>100</ns4:ExternalCompanyID>
            </ns4:CompanyInfo>
            <ns4:CustomerGroupName>1111</ns4:CustomerGroupName>
            </ns3:CustomerGroupReference>
                <ns3:Customer>
                    <ns4:CustomerReference referenceId="1">
                        <ns4:CustomerNumber>2222</ns4:CustomerNumber>
                    </ns4:CustomerReference>
                    <ns4:Detail>
                        <ns4:CustomerName>3333</ns4:CustomerName>
                        <ns4:CustomerNumber>Number</ns4:CustomerNumber>
                        <ns4:Country>aaa</ns4:Country>
                        <ns4:Address1>Address1</ns4:Address1>
                        <ns4:Address2>Address2</ns4:Address2>
                        <ns4:Region>Region</ns4:Region>
                        <ns4:City>City</ns4:City>
                        <ns4:ZipCode>ZipCode</ns4:ZipCode>          
                        <ns4:ContactName>ContactName</ns4:ContactName>
                        <ns4:ContactEmail>ContactEmail</ns4:ContactEmail>
                        <ns4:ContactPhone>ContactPhone</ns4:ContactPhone>
                    </ns4:Detail>
                </ns3:Customer>
        </ns3:Request>
        </ns3:CreateUpdateCustomer>
    </ns0:Body>
</ns0:Envelope>

Please help me understand the issue and point me in the right direction . Am I using the old python package ? should i be adding namespaces differently ? should i be parsing the file in the different way ?


Solution

  • As in the comments recommended, you have to register_namespace(), for example:

    import xml.etree.ElementTree as ET
    
    tree = ET.parse('Customer Request_In.xml')
    root = tree.getroot()
    
    namespaces = {node[0]: node[1] for event, node in ET.iterparse('Customer Request_In.xml', events=['start-ns'])}
    print("My Namespaces:", namespaces,'\n')
    for ns in namespaces:
        ET.register_namespace(ns, namespaces[ns])
    
    ExternalCompanyID = root.find('.//uli:ExternalCompanyID', namespaces)
    ExternalCompanyID.text = '100'
    
    CustomerName = root.find('.//uli:CustomerName', namespaces)
    CustomerName.text = '3333'
    
    Country = root.find('.//uli:Country', namespaces)
    Country.text = 'aaa'
    
    ET.dump(root)
    
    tree1 = ET.ElementTree(root)
    ET.indent(tree1, space= '  ')
    tree1.write('Customer.xml', encoding="utf-8")
    

    Input xml file:

    <?xml version='1.0' encoding='utf-8'?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hugo="hugo" xmlns:uli="uli">
      <soapenv:Body>
        <hugo:CreateUpdateCustomer>
          <hugo:Request>
            <hugo:CustomerGroupReference referenceId="1">
              <uli:CompanyInfo>
                <uli:ExternalCompanyID>111</uli:ExternalCompanyID>
              </uli:CompanyInfo>
              <uli:CustomerGroupName>1111</uli:CustomerGroupName>
            </hugo:CustomerGroupReference>
            <hugo:Customer>
              <uli:CustomerReference referenceId="1">
                <uli:CustomerNumber>2222</uli:CustomerNumber>
              </uli:CustomerReference>
              <uli:Detail>
                <uli:CustomerName>Name1</uli:CustomerName>
                <uli:CustomerNumber>Number1</uli:CustomerNumber>
                <uli:Country>CountryName</uli:Country>
                <uli:Address1>Address1</uli:Address1>
                <uli:Address2>Address2</uli:Address2>
                <uli:Region>Region</uli:Region>
                <uli:City>City</uli:City>
                <uli:ZipCode>ZipCode</uli:ZipCode>
                <uli:ContactName>ContactName</uli:ContactName>
                <uli:ContactEmail>ContactEmail</uli:ContactEmail>
                <uli:ContactPhone>ContactPhone</uli:ContactPhone>
              </uli:Detail>
            </hugo:Customer>
          </hugo:Request>
        </hugo:CreateUpdateCustomer>
      </soapenv:Body>
    </soapenv:Envelope>
    

    Output file:

    <?xml version='1.0' encoding='utf-8'?>
    <soapenv:Envelope xmlns:hugo="hugo" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:uli="uli">
      <soapenv:Body>
        <hugo:CreateUpdateCustomer>
          <hugo:Request>
            <hugo:CustomerGroupReference referenceId="1">
              <uli:CompanyInfo>
                <uli:ExternalCompanyID>100</uli:ExternalCompanyID>
              </uli:CompanyInfo>
              <uli:CustomerGroupName>1111</uli:CustomerGroupName>
            </hugo:CustomerGroupReference>
            <hugo:Customer>
              <uli:CustomerReference referenceId="1">
                <uli:CustomerNumber>2222</uli:CustomerNumber>
              </uli:CustomerReference>
              <uli:Detail>
                <uli:CustomerName>3333</uli:CustomerName>
                <uli:CustomerNumber>Number1</uli:CustomerNumber>
                <uli:Country>aaa</uli:Country>
                <uli:Address1>Address1</uli:Address1>
                <uli:Address2>Address2</uli:Address2>
                <uli:Region>Region</uli:Region>
                <uli:City>City</uli:City>
                <uli:ZipCode>ZipCode</uli:ZipCode>
                <uli:ContactName>ContactName</uli:ContactName>
                <uli:ContactEmail>ContactEmail</uli:ContactEmail>
                <uli:ContactPhone>ContactPhone</uli:ContactPhone>
              </uli:Detail>
            </hugo:Customer>
          </hugo:Request>
        </hugo:CreateUpdateCustomer>
      </soapenv:Body>
    </soapenv:Envelope>