Using Parsed XML Responses¶
New in version 1.0dev15: MWSResponse
and DotDict
added.
Warning
The following pertains to features added in v1.0dev15 related to MWS requests.
These features are disabled by default. To use these features, set flag _use_feature_mwsresponse
to True
on an API class instance before making any requests:
api_class = Orders(...)
api_class._use_feature_mwsresponse = True
If the flag is False
, all requests will return either DictWrapper
or DataWrapper
objects (deprecated);
and parsed XML contents will be returned as an instance of ObjectDict
(deprecated).
New features using MWSResponse
and DotDict
will become the default in v1.0.
For most MWS operations, the returned response is an XML documents encoded using ISO 8859-1. python-amazon-mws will wrap all responses
in an instance of MWSResponse
, which then parses these responses automatically
using the xmltodict
package. This parsed content is then available from the
MWSResponse.parsed
property.
Below, we’ll go into more detail on how to use MWSResponse.parsed
in your application to get the most from
these XML responses.
How XML responses are parsed in python-amazon-mws¶
XML responses from MWS typically look like the following example (adapted from an example in MWS documentation):
<?xml version="1.0"?>
<ListMatchingProductsResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<ListMatchingProductsResult>
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>059035342X</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Binding>Paperback</ns2:Binding>
<ns2:Brand>Scholastic Press</ns2:Brand>
<ns2:Creator Role="Illustrator">GrandPré, Mary</ns2:Creator>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
</Product>
</Products>
</ListMatchingProductsResult>
<ResponseMetadata>
<RequestId>3b805a12-689a-4367-ba86-EXAMPLE91c0b</RequestId>
</ResponseMetadata>
</ListMatchingProductsResponse>
Parsing of this document goes through the following steps in python-amazon-mws:
All requests are sent through the
requests
package, and responses are returned as arequests.Response
instance.The
Response
object is then wrapped byMWSResponse
, and stored internally asMWSResponse.original
.If the response did not specify an encoding in its headers,
MWSResponse
will call onrequests.Response.apparent_encoding
explicitly to force character set detection. For most use cases, this will allow theMWSResponse.text
property to decode the response content properly.Note
if a different encoding is required, you can alter
MWSResponse.encoding
before accessingMWSResponse.text
, or work with the rawMWSResponse.content
.You can also initialize an API class instance with a
force_response_encoding='my-encoding'
argument. This will override the encoding used to decode all responses from that API’s requests. This is useful when you are confident that responses are being encoded differently, such as when responses are actually encoded in UTF-8 (despite Amazon’s documentation to the contrary).MWSResponse.parse_response()
is called, which:Produces a “clean” copy of the XML document to use for parsing (see XML “cleaning” before parsing). (The original response content is left unchanged: only a copy is used for parsing.)
Runs
MWSResponse.text
through the utilitymws.utils.xml.mws_xml_to_dict
. This usesxmltodict.parse()
to convert the XML to a standard Python dictionary, which is returned and stored asMWSResponse._dict
.Wraps the parsed Python dict in a
DotDict
, which can be accessed fromMWSResponse.parsed
.If the response contains a
<ResponseMetadata>
tag, this method also builds aDotDict
instance of this key only, storing it asMWSResponse.metadata
. Typically this tag only contains the<RequestId>
element, so the propertyMWSResponse.request_id
can also be used to access this value.
Once parsing is complete, the MWSResponse
instance is returned. From this
instance, we can access the DotDict
that is returned from its
.parsed
property to comb through the returned data.
For more details on how to make the best use of this parsed data, please see DotDict.
Result keys and metadata¶
Most MWS requests returning XML documents take the following overall shape:
<?xml version="1.0"?>
<OperationResponse>
<OperationResult>
...
</OperationResult>
<ResponseMetadata>
<RequestId>...</RequestId>
</ResponseMetadata>
</OperationResponse>
The parsed document initially returns a dict
with just two keys. For the above example, that would look like so:
{
'OperationResult': ...,
'ResponseMetadata': ...,
}
Note
Operation
in all above examples would be replaced by the name of the MWS operation that was called.
For the ListInboundShipments
operation, for example, the document’s root will be
ListInboundShipmentsResponse
, and the result key will be ListInboundShipmentsResult
.
Both the ...Result
key and ResponseMetadata
are accessible from
MWSResponse
through separate properties:
The
...Result
key is used as the root forMWSResponse.parsed
, so accessing.parsed
should only return parsed content found inside the<...Result>
tag.ResponseMetadata
is accessible fromMWSResponse.metadata
. You can access theRequestId
stored there either asMWSResponse.metadata.RequestId
or through the shortcut property,MWSResponse.request_id
.
Tip
Amazon recommends
logging RequestId
as well as the request timestamp (found in
MWSResponse.timestamp
) to aid in troubleshooting when contacting
their support channels.
XML “cleaning” before parsing¶
MWS XML responses may be returned with a variety of data that does not fit well into Python data structures During parsing of these responses, python-amazon-mws either removes or finesses some of this data into a “cleaner” format.
Consider the example response from earlier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?xml version="1.0"?> <ListMatchingProductsResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01"> <ListMatchingProductsResult> <Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd"> <Product> <Identifiers> <MarketplaceASIN> <MarketplaceId>ATVPDKIKX0DER</MarketplaceId> <ASIN>059035342X</ASIN> </MarketplaceASIN> </Identifiers> <AttributeSets> <ns2:ItemAttributes xml:lang="en-US"> <ns2:Binding>Paperback</ns2:Binding> <ns2:Brand>Scholastic Press</ns2:Brand> <ns2:Creator Role="Illustrator">GrandPré, Mary</ns2:Creator> </ns2:ItemAttributes> </AttributeSets> <Relationships/> </Product> </Products> </ListMatchingProductsResult> <ResponseMetadata> <RequestId>3b805a12-689a-4367-ba86-EXAMPLE91c0b</RequestId> </ResponseMetadata> </ListMatchingProductsResponse> |
This document will be “cleaned” as follows:
The document’s root tag - in this case
<ListMatchingProductsResponse>
- will be ignored. The parsed Python dict will take the shape of:{ 'ListMatchingProductsResult': ..., 'ResponseMetadata': ... }
Namespaces are removed. For instance, the
<Products>
tag (line 4) will have both namespaces stripped, leaving only the bare tag name.Prefixes - such as
ns2:
orxml:
, seen on lines 13 through 17 - are removed from tag names and attributes. The tag<ns2:ItemAttributes xml:lang="en-US">
on line 13 will be stripped down to just<ItemAttributes lang="en-US">
prior to being parsed.