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
requestspackage, and responses are returned as arequests.Responseinstance.The
Responseobject is then wrapped byMWSResponse, and stored internally asMWSResponse.original.If the response did not specify an encoding in its headers,
MWSResponsewill call onrequests.Response.apparent_encodingexplicitly to force character set detection. For most use cases, this will allow theMWSResponse.textproperty to decode the response content properly.Note
if a different encoding is required, you can alter
MWSResponse.encodingbefore 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.textthrough 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 aDotDictinstance of this key only, storing it asMWSResponse.metadata. Typically this tag only contains the<RequestId>element, so the propertyMWSResponse.request_idcan 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
...Resultkey is used as the root forMWSResponse.parsed, so accessing.parsedshould only return parsed content found inside the<...Result>tag.ResponseMetadatais accessible fromMWSResponse.metadata. You can access theRequestIdstored there either asMWSResponse.metadata.RequestIdor 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.