やったこと
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を叩いた時に書いた以下の記事を参考にしてください。
ema-hiro.hatenablog.com
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するために書いたコードが以下にあります。
github.com
ハマったところ
API周りだと、ResponseGroupをいくつか追加で指定することができますが、複数指定する場合には ,
の後に 半角スペース
を入れてはいけということを知りました。
そのため、Itemの情報(ItemAttributes)だけでなく、Itemの画像を知りたい時は Images
というResponseGroupを追加することになるのですが、
params.Set("ResponseGroup", "ItemAttributes,Images")
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"`
}
xmlは親子関係をgolangで柔軟に表現できるので使い勝手がいいと感じました。