0

My extremely novice python/xml/coding aptitude has had me trying all day to unsuccessfully do something that I think should be pretty simple.

I've managed to send an XML request an a server, and the server generates a response that my script seems to be receiving, but I'd like to take the text response from the SessionID element that was returned and stick it into a variable that I can use later on.

It seems though that no matter what I try, I can't seem to get at that text.

I've been trying as best I can to wrap my head around the docs at https://docs.python.org/2/library/xml.etree.elementtree.html, but I'm not having much luck.

I'm sure it's something dumb, but I've hit a wall and I'm hoping someone can give me some guidance on a simple method to get to where I'm trying to go.

$ cat script.py

#!/usr/bin/python
import socket
import time
import xml.etree.ElementTree as ET

auth_request = '''\
<?xml version="1.0" encoding="UTF-8" ?>
<OSS xmlns="http://www.zhone.com/OSSXML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zhone.com/OSSXML ossxml.xsd">
        <Request>
                <RequestType>authenticate</RequestType>
        </Request>
        <RequestElement>
                <Attribute>
                        <Name>loginName</Name>
                        <Value>boss</Value>
                </Attribute>
                <Attribute>
                        <Name>password</Name>
                        <Value>snaky79!OCAS</Value>
                </Attribute>
        </RequestElement>
</OSS>
'''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("10.0.0.1", 15002))
s.send(auth_request)
buff = s.recv(400)
auth_response = ET.fromstring(buff)

print "Attempt 1:"
print auth_response.findall("*/SessionID")

print "Attempt 2:"
for a in auth_response.findall("*/status"):
        for b in a:
                print b
#print "Attempt 3:"
#c = auth_response.findall("*/status")
#for a in c:
#       print a.name
print "Attempt 4:"
print auth_response.getiterator()

print "Socket buffer:"
print buff

$./script.py

Attempt 1:
[<Element 'SessionID' at 0x1012a4d50>]
Attempt 2:
Attempt 4:
[<Element 'Response' at 0x1012a4950>, <Element 'OverAllStatus' at 0x1012a4990>, <Element 'OverAllDescription' at 0x1012a49d0>, <Element 'ResponseElement' at 0x1012a4a90>, <Element 'status' at 0x1012a4b50>, <Element 'Description' at 0x1012a4cd0>, <Element 'SessionID' at 0x1012a4d50>, <Element 'operName' at 0x1012a4d90>, <Element 'groupId' at 0x1012a4dd0>]
Socket buffer:
<Response>
<OverAllStatus>Success</OverAllStatus>
<OverAllDescription>The operation completed successfully</OverAllDescription>
<ResponseElement>
<status>Success</status>
<Description>Successfully Authenticated</Description>
<SessionID>0.379081153249641</SessionID>
<operName>boss</operName>
<groupId>99999</groupId>
</ResponseElement>
</Response>

FWIW, this is factory Python 2.7.10 on MacOS High Sierra.

Thanks!

2 Answers 2

4

For parsing xml, you can use xmltodict which will convert the xml response you are getting into dictionary, then you can easily retrieve the values of any key i.e. SessionId in your case.

import xmltodict 

response = xmltodict.parse(buff)

print response["Response"]["ResponseElement"]["SessionID"]

This will give you

0.379081153249641

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! This certainly seems simple enough. I'll give it a shot!
0

The issue is that in the pattern */SessionID the * component goes down only one level. If you properly format the XML to show the structure

<Response>
    <OverAllStatus>Success</OverAllStatus>
    <OverAllDescription>The operation completed successfully</OverAllDescription>
    <ResponseElement>
        <status>Success</status>
        <Description>Successfully Authenticated</Description>
        <SessionID>0.379081153249641</SessionID>
        <operName>boss</operName>
        <groupId>99999</groupId>
    </ResponseElement>
</Response>

you'll notice that both status and SessionID are nested two levels deep, so neither pattern works. The simplest solution is to use XPath syntax

findall("//SessionID")

This will find all SessionID elements regardless of how deeply nested they are.

1 Comment

Thank you! This is great info!

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.