David Vasandani
David Vasandani

Reputation: 1930

VERY BAD XML trying to parse with Python

I'm trying to use python to parse the xml output when after I purchase a domain name. So far I have:

#!/usr/bin/python

import sys
from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup

file = sys.argv[1]
xml = open(file).read()
soup = BeautifulStoneSoup(xml)
response = soup.find('ApiResponse')

print response

The XML output I'm working with is very malformed and definitely needs to be cleaned up.

ok: [162.243.95.241] => {"cache_control": "private", "changed": false, "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ApiResponse Status=\"OK\" xmlns=\"http://api.namecheap.com/xml.response\">\r\n  <Errors />\r\n  <Warnings />\r\n  <RequestedCommand>namecheap.domains.create</RequestedCommand>\r\n  <CommandResponse Type=\"namecheap.domains.create\">\r\n    <DomainCreateResult Domain=\"123er321test.com\" Registered=\"true\" ChargedAmount=\"8.1800\" DomainID=\"33404\" OrderID=\"414562\" TransactionID=\"679462\" WhoisguardEnable=\"false\" FreePositiveSSL=\"false\" NonRealTimeDomain=\"false\" />\r\n  </CommandResponse>\r\n  <Server>WEB1-SANDBOX1</Server>\r\n  <GMTTimeDifference>--5:00</GMTTimeDifference>\r\n  <ExecutionTime>9.008</ExecutionTime>\r\n</ApiResponse>", "content_length": "647", "content_location": "https://api.sandbox.namecheap.com/xml.response", "content_type": "text/xml; charset=utf-8", "date": "Thu, 21 Nov 2013 03:23:51 GMT", "item": "", "redirected": false, "server": "Microsoft-IIS/7.0", "status": 200, "x_aspnet_version": "4.0.30319", "x_powered_by": "ASP.NET"}

here is the "xml" again on pastebin.

I'm trying to find the ApiResponse Status which is either ERROR or OK

Upvotes: 2

Views: 310

Answers (1)

abarnert
abarnert

Reputation: 365617

There's absolutely nothing wrong with the XML there.

The problem is that the XML is embedded in JSON, which is itself embedded in some kind of object that I can't immediately identify. (My suspicion is that you've just dumped out the repr of some kind of object from whatever framework you were using to make the request, which was a silly thing to do…)

So, parse the top-level thing in the appropriate way for whatever format it is. (If you have no idea where it came from, it looks like you could easily just do .partition('=>')[-1].) Then parse the JSON with json.loads. Then get the ['content'] of the resulting dict, which is the XML, which you can parse with BeautifulSoup. Then you're done.

In other words:

>>> thingy = r''' ok: [162.243.95.241] => {"cache_control": "private", "changed": false, "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ApiResponse Status=\"OK\" xmlns=\"http://api.namecheap.com/xml.response\">\r\n  <Errors />\r\n  <Warnings />\r\n  <RequestedCommand>namecheap.domains.create</RequestedCommand>\r\n  <CommandResponse Type=\"namecheap.domains.create\">\r\n    <DomainCreateResult Domain=\"123er321test.com\" Registered=\"true\" ChargedAmount=\"8.1800\" DomainID=\"33404\" OrderID=\"414562\" TransactionID=\"679462\" WhoisguardEnable=\"false\" FreePositiveSSL=\"false\" NonRealTimeDomain=\"false\" />\r\n  </CommandResponse>\r\n  <Server>WEB1-SANDBOX1</Server>\r\n  <GMTTimeDifference>--5:00</GMTTimeDifference>\r\n  <ExecutionTime>9.008</ExecutionTime>\r\n</ApiResponse>", "content_length": "647", "content_location": "https://api.sandbox.namecheap.com/xml.response", "content_type": "text/xml; charset=utf-8", "date": "Thu, 21 Nov 2013 03:23:51 GMT", "item": "", "redirected": false, "server": "Microsoft-IIS/7.0", "status": 200, "x_aspnet_version": "4.0.30319", "x_powered_by": "ASP.NET"}'''
>>> j = thingy.partition('=>')[-1]
>>> obj = json.loads(j)
>>> xml = obj['content']
>>> soup = BeautifulSoup(xml)
>>> soup
<?xml version="1.0" encoding="utf-8"?>
<apiresponse status="OK" xmlns="http://api.namecheap.com/xml.response">
<errors></errors>
<warnings></warnings>
<requestedcommand>namecheap.domains.create</requestedcommand>
<commandresponse type="namecheap.domains.create">
<domaincreateresult chargedamount="8.1800" domain="123er321test.com" domainid="33404" freepositivessl="false" nonrealtimedomain="false" orderid="414562" registered="true" transactionid="679462" whoisguardenable="false"></domaincreateresult>
</commandresponse>
<server>WEB1-SANDBOX1</server>
<gmttimedifference>--5:00</gmttimedifference>
<executiontime>9.008</executiontime>
</apiresponse>
>>> soup.find('apiresponse')['status']
'OK'

Upvotes: 4

Related Questions