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>"
}
Answer from jfs on Stack OverflowJust 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.
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?
python - POST XML file with requests - Stack Overflow
Post Request grabs xml in postman, but when I use the python requests code generated it doesn't run
XML file upload in requests library
Posting XML data in the body of a post request leads to an error
Videos
Hey all,
I have been trying to debug this for a few hours now.
I am POSTing data to an endpoint where the body must be an XML.
I have taken my Postman request and saved it as a XML and I am passing it into a requests.post() in python.
Every time I get an error message. Looking at App Insights on the API side I see that the last 2 symbols from the XML are missing the XML end as:
</dataElemen
where it should end up like:
</dataElement>
In python I do not modify the XML file. The XML file is a copy of the XML from Postman that works as expected.
The only explanation that I have is that Content-Length gets overwritten when the post request is executed because I tried adding + 2 to the length to account for the 2 last missing symbols.
The xml is utf-8 and there is nothing unusual about it.
Do you have any suggestions what I can try to pass the correct xml?
Link to code - https://imgur.com/a/lGgk6J5 (there is a bit of sensitive data that I have redacted, that is why I am pasting an image)
Once, when I had to do a similar thing, I did like this:
requests.post(url, data=xml_string, headers={'Content-Type':'application/xml; charset=UTF-8'})
Not a requests method, but here's a real simple recipe using urllib2 from my codebase:
import urllib2
from elementtree import ElementTree
def post(url, data, contenttype):
request = urllib2.Request(url, data)
request.add_header('Content-Type', contenttype)
response = urllib2.urlopen(request)
return response.read()
def postxml(url, elem):
data = ElementTree.tostring(elem, encoding='UTF-8')
return post(url, data, 'text/xml')
I suspect what you're missing is the use of tostring to convert the ElementTree Element that you named root.
It's common to return a 200 response even when a 201 response would strictly be more appropriate. Are you sure that the request isn't correctly processed even if you are getting a 'correct' response?
You're using a local opener everywhere except on the line where you create the response, where you use self.opener, which looks like the problem.
you should try like this
def frame_xml(AddressVerified,AmountPaid):
xml_data = """<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/ metadata" xmlns="http://www.w3.org/2005/Atom">
<category scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" term="SS.WebData.Order" />
<title />
<author>
<name />
</author>
<id />
<content type="application/xml">
<m:properties>
<d:AddressVerified m:type="Edm.Byte">%s</d:AddressVerified>
<d:AmountPaid m:type="Edm.Decimal">%s</d:AmountPaid>
</m:properties>
</content>
</entry>"""%(AddressVerified,AmountPaid)
return xml_data
headers = {'Content-Type': 'application/xml'}
xml_data = frame_xml('AddressVerified','AmountPaid')
print requests.post('https://data.shipstation.com/1.2/Orders', data=xml_data, headers=headers).text
Use Python requests module. Some examples you can find on quick-start page:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print r.text
...
Or
>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
...
See more here: How can I send an xml body using requests library?