3

is it possible to construct a XML as this one using lxml?

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns0="http://xmlns.CLT.com/consume/ENTBUS" xmlns:ns1="http://xmlns.CLT.com/Core/ENTBUS" xmlns:ns2="http://xmlns.CLT.com/output/EBO">
   <soapenv:Header/>
   <soapenv:Body>
      <ns0:ConsumptionRequestENTBUS>
         <ns1:ENTBUSHeader>
            <ns1:ENTBUSID>1</ns1:ENTBUSID>
         </ns1:ENTBUSHeader>
         <ns0:Zone>
            <ns2:Consumption>
               <ns2:BusCode>1</ns2:BusCode>
            </ns2:Consumption>
         </ns0:Zone>
      </ns0:ConsumptionRequestENTBUS>
   </soapenv:Body>
</soapenv:Envelope>

I tried building the root element as below but it fails. And almost every element needs to be namespace referenced.

>>> from lxml import etree
>>> root = etree.Element("soapenv:Envelope")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lxml.etree.pyx", line 2811, in lxml.etree.Element (src\lxml\lxml.etree.c:65389)
  File "apihelpers.pxi", line 103, in lxml.etree._makeElement (src\lxml\lxml.etree.c:13898)
  File "apihelpers.pxi", line 1575, in lxml.etree._tagValidOrRaise (src\lxml\lxml.etree.c:27955)
ValueError: Invalid tag name u'soapenv:Envelope'

Thanks

3 Answers 3

1

I was able to solve this in the following manner. Any suggestions to make this better are most welcome.

>>> from lxml import etree
>>> SOAPENV_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope"
>>> SOAPENV = "{%s}" % SOAPENV_NAMESPACE
>>> ns0_NAMESPACE = "http://xmlns.CLT.com/consume/ENTBUS"
>>> ns0 = "{%s}" % ns0_NAMESPACE
>>> ns1_NAMESPACE = "http://xmlns.CLT.com/Core/ENTBUS"
>>> ns1 = "{%s}" % ns1_NAMESPACE
>>> ns2_NAMESPACE = "http://xmlns.CLT.com/output/EBO"
>>> ns2 = "{%s}" % ns2_NAMESPACE
>>> NSMAP = {'SoapEnv' : SOAPENV_NAMESPACE,'ns0':ns0_NAMESPACE,'ns1':ns1_NAMESPACE,'ns2':ns2_NAMESPACE}
>>> envelope = etree.Element(SOAPENV + "Envelope", nsmap=NSMAP)
>>> ConsumptionRequestENTBUS=etree.SubElement(envelope, ns0 + "ConsumptionRequestENTBUS", nsmap=NSMAP)
>>> ENTBUS=etree.SubElement(ConsumptionRequestENTBUS, ns1 + "ENTBUS", nsmap=NSMAP)
>>> ENTBUSHeader=etree.SubElement(ENTBUS, ns1 + "ENTBUSHeader", nsmap=NSMAP)
>>> ENTBUSDetail=etree.SubElement(ENTBUSHeader, ns2 + "ENTBUSDetail", nsmap=NSMAP)
>>> print(etree.tostring(envelope, pretty_print=True))
<SoapEnv:Envelope xmlns:ns0="http://xmlns.CLT.com/consume/ENTBUS" xmlns:ns1="http://xmlns.CLT.com/Core/ENTBUS" xmlns:ns2="h
ttp://xmlns.CLT.com/output/EBO" xmlns:SoapEnv="http://schemas.xmlsoap.org/soap/envelope">
  <ns0:ConsumptionRequestENTBUS>
    <ns1:ENTBUS>
      <ns1:ENTBUSHeader>
        <ns2:ENTBUSDetail/>
      </ns1:ENTBUSHeader>
    </ns1:ENTBUS>
  </ns0:ConsumptionRequestENTBUS>
</SoapEnv:Envelope>
Sign up to request clarification or add additional context in comments.

Comments

0

The lxml tutorial does have a section on namespaces. However, if you're actually communicating with a SOAP webservice, I'd recommend using a proper library like suds or soapbox if possible.

1 Comment

soapbox is far from complete.I am usig jurko-suds and it fails to map namespaces. So I am down to building the request this way. Will it be possible for you to help me 1 to 1 with a suds question?
0

Not sure if it's better but an alternative way to do it would be:

from lxml import etree
from lxml.builder import ElementMaker


nslist = {
        'soapenv':'http://schemas.xmlsoap.org/soap/envelope/',
        'ns0':'http://xmlns.CLT.com/consume/ENTBUS',
        'ns1':'http://xmlns.CLT.com/Core/ENTBUS',
        'ns2':'http://xmlns.CLT.com/output/EBO', 
        None: 'http://schemas.xmlsoap.org/soap/envelope/'}
 
E = ElementMaker(namespace="http://schemas.xmlsoap.org/soap/envelope/", nsmap=nslist)
E0 = ElementMaker(namespace="http://xmlns.CLT.com/consume/ENTBUS", nsmap={'ns0':'http://xmlns.CLT.com/consume/ENTBUS'})
E1 = ElementMaker(namespace="http://xmlns.CLT.com/Core/ENTBUS", nsmap={'ns0':'http://xmlns.CLT.com/Core/ENTBUS'})
E2 = ElementMaker(namespace="http://xmlns.CLT.com/output/EBO", nsmap={'ns2':'http://xmlns.CLT.com/output/EBO'})

out = E.Envelope(
    E.Header(), 
    E.Body(
        E0.ConsumptionRequestENTBUS(
            E1.ENTBUSHeader(
                E1.ENTBUSID('1')
            ),
            E0.Zone(
                E2.Consumption(
                    E2.BusCode('1')
                )
            )
        )
    )
)

print(etree.tostring(out, encoding="UTF-8", standalone="yes", pretty_print=True))

Comments

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.