やったこと
Amazon Product Advertising APIを使ってISBNから書籍情報を取得するプログラムを書く際に、AmazonのAPIのレスポンスは json ではなく、xmlでデータが帰ってくるので、このxmlをGolangでparseするためにしました。
※ 今時xmlかよ!っと思ってちょっとびっくりしたのは秘密。
Parse XML Response in Go
Golangに置いて、xmlをparseするには encoding/xml
を使います。
jsonをparseするときと同様にデータ構造をstructにMappingする際に、明示的にxmlでのタグを追加します。
ex) Amazon Product Advertising API - Operation - ItemLookup の場合
type ItemLookupResponse struct { XMLName xml.Name `xml:"ItemLookupResponse"` // ここ!! Items Items `xml:"Items"` }
Sample
Amazon Product Advertising APIを叩いてレスポンス(xml)を取得します。
取得の方法は以前Amazon Product Advertising APIを叩いた時に書いた以下の記事を参考にしてください。
ResponseGroup は ItemAttributes
を指定しています。
※ 書籍は同僚でいつもお世話になっているyoichiro san の最新の著書を使わせてもらってます。
"<?xml version=\"1.0\" ?><ItemLookupResponse xmlns=\"http://webservices.amazon.com/AWSECommerceService/2011-08-01\"><OperationRequest><HTTPHeaders><Header Name=\"UserAgent\" Value=\"Go-http-client/1.1\"></Header></HTTPHeaders><RequestId>e715307c-950e-4a5f-80d8-bc90d09c0ce9</RequestId><Arguments><Argument Name=\"AWSAccessKeyId\" Value=\"AKIAI43PAKG3WCIFW2DQ\"></Argument><Argument Name=\"AssociateTag\" Value=\"emahiro-22\"></Argument><Argument Name=\"IdType\" Value=\"ISBN\"></Argument><Argument Name=\"ItemId\" Value=\"9784774193328\"></Argument><Argument Name=\"Operation\" Value=\"ItemLookup\"></Argument><Argument Name=\"ResponseGroup\" Value=\"ItemAttributes\"></Argument><Argument Name=\"SearchIndex\" Value=\"Books\"></Argument><Argument Name=\"Service\" Value=\"AWSECommerceService\"></Argument><Argument Name=\"Timestamp\" Value=\"2017-12-11T17:25:44Z\"></Argument><Argument Name=\"Signature\" Value=\"Ak5Lz77ab+aGuBgz9eLuPRMqP092drq+Yqmp455DlAA=\"></Argument></Arguments><RequestProcessingTime>0.0137283900000000</RequestProcessingTime></OperationRequest><Items><Request><IsValid>True</IsValid><ItemLookupRequest><IdType>ISBN</IdType><ItemId>9784774193328</ItemId><ResponseGroup>ItemAttributes</ResponseGroup><SearchIndex>Books</SearchIndex><VariationPage>All</VariationPage></ItemLookupRequest></Request><Item><ASIN>4774193321</ASIN><DetailPageURL>https://www.amazon.co.jp/%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E6%A7%8B%E7%AF%89%E6%8A%80%E6%B3%95%E2%80%95%E2%80%95SNS%E3%81%8B%E3%82%89BOT%E3%81%BE%E3%81%A7IT%E3%82%92%E3%82%B3%E3%82%A2%E3%81%AB%E6%88%90%E9%95%B7%E3%81%99%E3%82%8B%E4%BC%81%E6%A5%AD%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-Software-Design-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E6%B4%8B%E4%B8%80%E9%83%8E/dp/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=165953&creativeASIN=4774193321</DetailPageURL><ItemLinks><ItemLink><Description>Add To Wishlist</Description><URL>https://www.amazon.co.jp/gp/registry/wishlist/add-item.html?asin.0=4774193321&SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL></ItemLink><ItemLink><Description>Tell A Friend</Description><URL>https://www.amazon.co.jp/gp/pdp/taf/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL></ItemLink><ItemLink><Description>All Customer Reviews</Description><URL>https://www.amazon.co.jp/review/product/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL></ItemLink><ItemLink><Description>All Offers</Description><URL>https://www.amazon.co.jp/gp/offer-listing/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL></ItemLink></ItemLinks><ItemAttributes><Author>田中 洋一郎</Author><Binding>単行本(ソフトカバー)</Binding><EAN>9784774193328</EAN><EANList><EANListElement>9784774193328</EANListElement></EANList><IsAdultProduct>0</IsAdultProduct><ISBN>4774193321</ISBN><Label>技術評論社</Label><Languages><Language><Name>日本語</Name><Type>Published</Type></Language></Languages><Manufacturer>技術評論社</Manufacturer><NumberOfPages>360</NumberOfPages><PackageDimensions><Height Units=\"100分の1インチ\">71</Height><Length Units=\"100分の1インチ\">835</Length><Weight Units=\"100分の1ポンド\">97</Weight><Width Units=\"100分の1インチ\">591</Width></PackageDimensions><ProductGroup>Book</ProductGroup><ProductTypeName>ABIS_BOOK</ProductTypeName><PublicationDate>2017-10-20</PublicationDate><Publisher>技術評論社</Publisher><Studio>技術評論社</Studio><Title>ソーシャルアプリプラットフォーム構築技法――SNSからBOTまでITをコアに成長する企業の教科書 (Software Design plusシリーズ)</Title></ItemAttributes></Item><Item><ASIN>B076GXMNFN</ASIN><DetailPageURL>https://www.amazon.co.jp/%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E6%A7%8B%E7%AF%89%E6%8A%80%E6%B3%95-%E2%80%95%E2%80%95SNS%E3%81%8B%E3%82%89BOT%E3%81%BE%E3%81%A7IT%E3%82%92%E3%82%B3%E3%82%A2%E3%81%AB%E6%88%90%E9%95%B7%E3%81%99%E3%82%8B%E4%BC%81%E6%A5%AD%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-Software-Design-plus-ebook/dp/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B076GXMNFN</DetailPageURL><ItemLinks><ItemLink><Description>Add To Wishlist</Description><URL>https://www.amazon.co.jp/gp/registry/wishlist/add-item.html?asin.0=B076GXMNFN&SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL></ItemLink><ItemLink><Description>Tell A Friend</Description><URL>https://www.amazon.co.jp/gp/pdp/taf/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL></ItemLink><ItemLink><Description>All Customer Reviews</Description><URL>https://www.amazon.co.jp/review/product/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL></ItemLink><ItemLink><Description>All Offers</Description><URL>https://www.amazon.co.jp/gp/offer-listing/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL></ItemLink></ItemLinks><ItemAttributes><Author>田中 洋一郎</Author><Binding>Kindle版</Binding><EISBN>9784774193687</EISBN><Format>Kindle本</Format><IsAdultProduct>0</IsAdultProduct><Label>技術評論社</Label><Languages><Language><Name>日本語</Name><Type>Published</Type></Language></Languages><Manufacturer>技術評論社</Manufacturer><NumberOfPages>602</NumberOfPages><ProductGroup>eBooks</ProductGroup><ProductTypeName>ABIS_EBOOKS</ProductTypeName><PublicationDate>2017-10-20</PublicationDate><Publisher>技術評論社</Publisher><ReleaseDate>2017-10-20</ReleaseDate><Studio>技術評論社</Studio><Title>ソーシャルアプリプラットフォーム構築技法 ――SNSからBOTまでITをコアに成長する企業の教科書 Software Design plus</Title></ItemAttributes></Item></Items></ItemLookupResponse>"
ItemAttributes
をResponseGroup
として指定した時の上記のようなxmlが返ってきても、生のxmlは可読性が悪いので、以下のようなサービスを使ってresponseのxmlを見やすい形に整形して、一つ一つ構造体にmappingしていきます。
http://u670.com/pikamap/htmlseikei.php
<?xml version=\"1.0\" ?> <ItemLookupResponse xmlns=\"http://webservices.amazon.com/AWSECommerceService/2011-08-01\"> <OperationRequest> <HTTPHeaders> <Header Name=\"UserAgent\" Value=\"Go-http-client/1.1\"></Header> </HTTPHeaders> <RequestId>e7d362b0-abe9-42a1-9cc1-ef9943303e12</RequestId> <Arguments> <Argument Name=\"AWSAccessKeyId\" Value=\"AKIAI43PAKG3WCIFW2DQ\"></Argument> <Argument Name=\"AssociateTag\" Value=\"emahiro-22\"></Argument> <Argument Name=\"IdType\" Value=\"ISBN\"></Argument> <Argument Name=\"ItemId\" Value=\"9784774193328\"></Argument> <Argument Name=\"Operation\" Value=\"ItemLookup\"></Argument> <Argument Name=\"ResponseGroup\" Value=\"ItemAttributes\"></Argument> <Argument Name=\"SearchIndex\" Value=\"Books\"></Argument> <Argument Name=\"Service\" Value=\"AWSECommerceService\"></Argument> <Argument Name=\"Timestamp\" Value=\"2017-12-12T16:28:21Z\"></Argument> <Argument Name=\"Signature\" Value=\"MGrC8pmelta5xLNmwDTSH3HdmksJvE5PieDTu9lOqzE=\"></Argument> </Arguments> <RequestProcessingTime>0.0108954000000000</RequestProcessingTime> </OperationRequest> <Items> <Request> <IsValid>True</IsValid> <ItemLookupRequest> <IdType>ISBN</IdType> <ItemId>9784774193328</ItemId> <ResponseGroup>ItemAttributes</ResponseGroup> <SearchIndex>Books</SearchIndex> <VariationPage>All</VariationPage> </ItemLookupRequest> </Request> <Item> <ASIN>4774193321</ASIN> <DetailPageURL>https://www.amazon.co.jp/%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E6%A7%8B%E7%AF%89%E6%8A%80%E6%B3%95%E2%80%95%E2%80%95SNS%E3%81%8B%E3%82%89BOT%E3%81%BE%E3%81%A7IT%E3%82%92%E3%82%B3%E3%82%A2%E3%81%AB%E6%88%90%E9%95%B7%E3%81%99%E3%82%8B%E4%BC%81%E6%A5%AD%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-Software-Design-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E6%B4%8B%E4%B8%80%E9%83%8E/dp/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=165953&creativeASIN=4774193321</DetailPageURL> <ItemLinks> <ItemLink> <Description>Add To Wishlist</Description> <URL>https://www.amazon.co.jp/gp/registry/wishlist/add-item.html?asin.0=4774193321&SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL> </ItemLink> <ItemLink> <Description>Tell A Friend</Description> <URL>https://www.amazon.co.jp/gp/pdp/taf/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL> </ItemLink> <ItemLink> <Description>All Customer Reviews</Description> <URL>https://www.amazon.co.jp/review/product/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL> </ItemLink> <ItemLink> <Description>All Offers</Description> <URL>https://www.amazon.co.jp/gp/offer-listing/4774193321?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=4774193321</URL> </ItemLink> </ItemLinks> <ItemAttributes> <Author>田中 洋一郎</Author> <Binding>単行本(ソフトカバー)</Binding> <EAN>9784774193328</EAN> <EANList> <EANListElement>9784774193328</EANListElement> </EANList> <IsAdultProduct>0</IsAdultProduct> <ISBN>4774193321</ISBN> <Label>技術評論社</Label> <Languages> <Language> <Name>日本語</Name> <Type>Published</Type> </Language> </Languages> <Manufacturer>技術評論社</Manufacturer> <NumberOfPages>360</NumberOfPages> <PackageDimensions> <Height Units=\"100分の1インチ\">71</Height> <Length Units=\"100分の1インチ\">835</Length> <Weight Units=\"100分の1ポンド\">97</Weight> <Width Units=\"100分の1インチ\">591</Width> </PackageDimensions> <ProductGroup>Book</ProductGroup> <ProductTypeName>ABIS_BOOK</ProductTypeName> <PublicationDate>2017-10-20</PublicationDate> <Publisher>技術評論社</Publisher> <Studio>技術評論社</Studio> <Title>ソーシャルアプリプラットフォーム構築技法――SNSからBOTまでITをコアに成長する企業の教科書 (Software Design plusシリーズ)</Title> </ItemAttributes> </Item> <Item> <ASIN>B076GXMNFN</ASIN> <DetailPageURL>https://www.amazon.co.jp/%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E6%A7%8B%E7%AF%89%E6%8A%80%E6%B3%95-%E2%80%95%E2%80%95SNS%E3%81%8B%E3%82%89BOT%E3%81%BE%E3%81%A7IT%E3%82%92%E3%82%B3%E3%82%A2%E3%81%AB%E6%88%90%E9%95%B7%E3%81%99%E3%82%8B%E4%BC%81%E6%A5%AD%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-Software-Design-plus-ebook/dp/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B076GXMNFN</DetailPageURL> <ItemLinks> <ItemLink> <Description>Add To Wishlist</Description> <URL>https://www.amazon.co.jp/gp/registry/wishlist/add-item.html?asin.0=B076GXMNFN&SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL> </ItemLink> <ItemLink> <Description>Tell A Friend</Description> <URL>https://www.amazon.co.jp/gp/pdp/taf/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL> </ItemLink> <ItemLink> <Description>All Customer Reviews</Description> <URL>https://www.amazon.co.jp/review/product/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL> </ItemLink> <ItemLink> <Description>All Offers</Description> <URL>https://www.amazon.co.jp/gp/offer-listing/B076GXMNFN?SubscriptionId=AKIAI43PAKG3WCIFW2DQ&tag=emahiro-22&linkCode=xm2&camp=2025&creative=5143&creativeASIN=B076GXMNFN</URL> </ItemLink> </ItemLinks> <ItemAttributes> <Author>田中 洋一郎</Author> <Binding>Kindle版</Binding> <EISBN>9784774193687</EISBN> <Format>Kindle本</Format> <IsAdultProduct>0</IsAdultProduct> <Label>技術評論社</Label> <Languages> <Language> <Name>日本語</Name> <Type>Published</Type> </Language> </Languages> <Manufacturer>技術評論社</Manufacturer> <NumberOfPages>602</NumberOfPages> <ProductGroup>eBooks</ProductGroup> <ProductTypeName>ABIS_EBOOKS</ProductTypeName> <PublicationDate>2017-10-20</PublicationDate> <Publisher>技術評論社</Publisher> <ReleaseDate>2017-10-20</ReleaseDate> <Studio>技術評論社</Studio> <Title>ソーシャルアプリプラットフォーム構築技法 ――SNSからBOTまでITをコアに成長する企業の教科書 Software Design plus</Title> </ItemAttributes> </Item> </Items> </ItemLookupResponse>
構造化されたxmlのレスポンスを取得することができました。 このようなxmlの構造をstructにMappingするために書いたコードが以下にあります。
ハマったところ
API周りだと、ResponseGroupをいくつか追加で指定することができますが、複数指定する場合には ,
の後に 半角スペース
を入れてはいけということを知りました。
そのため、Itemの情報(ItemAttributes)だけでなく、Itemの画像を知りたい時は Images
というResponseGroupを追加することになるのですが、
// OK params.Set("ResponseGroup", "ItemAttributes,Images") // NG params.Set("ResponseGroup", "ItemAttributes, Images") // 半角スペースが入ってしまっている。
となります。
また、xmlの構造をStructにMappingする時に
type ItemAttributes struct { XMLName xml.Name `xml:"ItemAttributes"` Author []string `xml:"Author"` Binding string `xml:"Binding"` EAN int64 `xml:"EAN"` EANList EANList `xml:"EANList"` IsAdultProduct bool `xml:"IsAdultProduct"` ISBN string `xml:"ISBN"` Label string `xml:"Label"` Languages Languages `xml:"Languages"` Manufacturer string `xml:"Manufacturer"` NumberOfPages int64 `xml:"NumberOfPages"` PackageDimensions PackageDimensions `xml:"PackageDimensions"` ProductGroup string `xml:"ProductGroup"` ProductTypeName string `xml:"ProductTypeName"` PublicationDate string `xml:"PublicationDate"` Publisher string `xml:"Publisher"` Studio string `xml:"Studio"` Title string `xml:"Title"` }
のような構造において Languages
fieldを考える時に、通常なら
type Language struct { XMLName xml.Name `xml:"Language"` Name string `xml:"Name"` Type string `xml:"Type"` }
という Language
のStruct(Model)を用意して、
// 略 Languages []Language `xml:"Languages"`
のように、明示的に配列がデータ構造としてはいることがわかりそうなものですが、上記の記載方法だとUnmarshalする時にエラーになってしまいます。
xmlをParseする際には、以下のような中間Structを定義しないと正確にUnmarshalされないことを知りました。
type Languages struct { XMLName xml.Name `xml:"Languages"` Language []Language `xml:"Language"` }
Languages
タグはあくまで Languages
タグであり、その中に Language
が配列として入っている、というタグの構造を理解せず、 JsonをMappingするときの感覚だと失敗しました。
追記
xmlは >
を使って親子関係を表現できます。
ItemAttributes
のstructの構造において
EANListの構造は以下
EANList EANListElement
Languagesの構造は以下
Languages []Language
という構造を表現するのにstructを二つ作って親子関係を表現していました。
しかし、 >
を使って xmlの定義の箇所で親子関係を表現させることが可能です。
なので ItemAttributes
のstructは以下のように変更可能になります。
package model import "encoding/xml" type ItemAttributes struct { XMLName xml.Name `xml:"ItemAttributes"` Author []string `xml:"Author"` Binding string `xml:"Binding"` EAN int64 `xml:"EAN"` EANList int64 `xml:"EANList>EANListElement"` // ここ IsAdultProduct bool `xml:"IsAdultProduct"` ISBN string `xml:"ISBN"` Label string `xml:"Label"` Languages []Language `xml:"Languages>Language"` // ここ Manufacturer string `xml:"Manufacturer"` NumberOfPages int64 `xml:"NumberOfPages"` PackageDimensions PackageDimensions `xml:"PackageDimensions"` ProductGroup string `xml:"ProductGroup"` ProductTypeName string `xml:"ProductTypeName"` PublicationDate string `xml:"PublicationDate"` Publisher string `xml:"Publisher"` Studio string `xml:"Studio"` Title string `xml:"Title"` } type Language struct { XMLName xml.Name `xml:"Language"` Name string `xml:"Name"` Type string `xml:"Type"` } type PackageDimensions struct { XMLName xml.Name `xml:"PackageDimensions"` Height int64 `xml:"Height"` Length int64 `xml:"Length"` Weight int64 `xml:"Weight"` Width int64 `xml:"Width"` }