requests does not handle parsing XML responses, no. XML responses are much more complex in nature than JSON responses, how you'd serialize XML data into Python structures is not nearly as straightforward.
Python comes with built-in XML parsers. I recommend you use the ElementTree API:
import requests
from xml.etree import ElementTree
response = requests.get(url)
tree = ElementTree.fromstring(response.content)
or, if the response is particularly large, use an incremental approach:
response = requests.get(url, stream=True)
# if the server sent a Gzip or Deflate compressed response, decompress
# as we read the raw stream:
response.raw.decode_content = True
events = ElementTree.iterparse(response.raw)
for event, elem in events:
# do something with `elem`
The external lxml project builds on the same API to give you more features and power still.
Answer from Martijn Pieters on Stack Overflowrequests does not handle parsing XML responses, no. XML responses are much more complex in nature than JSON responses, how you'd serialize XML data into Python structures is not nearly as straightforward.
Python comes with built-in XML parsers. I recommend you use the ElementTree API:
import requests
from xml.etree import ElementTree
response = requests.get(url)
tree = ElementTree.fromstring(response.content)
or, if the response is particularly large, use an incremental approach:
response = requests.get(url, stream=True)
# if the server sent a Gzip or Deflate compressed response, decompress
# as we read the raw stream:
response.raw.decode_content = True
events = ElementTree.iterparse(response.raw)
for event, elem in events:
# do something with `elem`
The external lxml project builds on the same API to give you more features and power still.
A much simpler way is to convert the XML into a dict using the xmltodict package
response = requests.get('http://blabla.com')
dict_data = xmltodict.parse(response.content)
Now, dict_data it's just a Python dictionary.
You can install it with pip: pip install xmltodict
How do I send an xml request and receive an xml response in Python? - Stack Overflow
Posting XML Data to an API using Python Requests & ElementTree/lxml
python - How can I send an xml body using requests library? - Stack Overflow
Simple XML Parsing in Python
Videos
You can use the urllib2 module that comes with Python to make requests to a URL that can consume this.
The Python website has a decent tutorial on how to use this module to fetch internet resources. The next step is learning how to generate/consume XML.
Related SO answers for those steps:
- Generating XML
- Consuming XML
I have posted a small example of plain XML request and response in Python here:
http://it.toolbox.com/blogs/lim/request-get-reply-and-display-xml-in-python-beauty-of-simplicity-49791
Please not that my example posts arbitrary XML and gets a valid XML but that informs you of an error because the content of the request was not recognized.
You could use your own URL and XML or adjust not to send XML request and just parse the response against the provided XML.
I would also suggest looking into eBays example for their x.Commerce XML API accessed from Python.
Hope this helps.
Hello
I'm currently trying to post an XML string to an API that i've created from a pandas DataFrame using LXML (mainly because ElementTree doesn't have an xml_declaration=True parameter?). However i seem to be receiving an 400 status code within the response.
xml_data = ET.tostring(root, encoding='UTF-8', xml_declaration=True)
url = api_url + version + endpoint
headers = {
"Content-Type": "application/xml"
}
params = {
"access_token": access_token
}
response = r.post(url, headers=headers, params=params, data=xml_data) I have noticed when printing my XML string (and also running it through an XML validator) there is a line break after my XML Declaration that the validator didn't seem to like:
"<?xml version=\\\\'1.0\\\\' encoding=\\\\'UTF-8\\\\'?>\n"
Could it be this causing the 400 error code? If so, how can i remove the line break from the string given it's a "Bytes" data type instead of "String" after the ET.tostring() function?
Or is there anything else noticeably wrong about this xml declaration?
Thanks
EDIT:
The response text error i'm actually getting is:
{"error":{"message":"(#10801) Either \"file\" or \"url\" must be specified.","type":"OAuthException","code":10801}}
So is it that i'm actually passing the data into requests incorrectly?
Just send xml bytes directly:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import requests
xml = """<?xml version='1.0' encoding='utf-8'?>
<a>б</a>"""
headers = {'Content-Type': 'application/xml'} # set what your server accepts
print requests.post('http://httpbin.org/post', data=xml, headers=headers).text
Output
{
"origin": "x.x.x.x",
"files": {},
"form": {},
"url": "http://httpbin.org/post",
"args": {},
"headers": {
"Content-Length": "48",
"Accept-Encoding": "identity, deflate, compress, gzip",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "python-requests/0.13.9 CPython/2.7.3 Linux/3.2.0-30-generic",
"Host": "httpbin.org",
"Content-Type": "application/xml"
},
"json": null,
"data": "<?xml version='1.0' encoding='utf-8'?>\n<a>\u0431</a>"
}
Pass in the straight XML instead of a dictionary.