ぽぴ王子の人生プログラミング中

~デバッグもあるでよ!~

目次

ニュース

日記カテゴリ

書庫

Blog 利用状況

リンク

XMLでごにょごにょ

年末からちょっとヒマだったので、少しXMLについて調べていました。と言ってもXMLというよりはAmazon Web サービス(以下AWS)の研究というか、そんな感じで。

面倒なのでAWSについての説明は省いてしまいますが(必要な場合はコメントで「書けよコラ!ジャンプしてみろよ!持ってんじゃねえか!」とか書いてみてください)webservices.amazon.co.jpにリクエストを投げると、必要なデータを返してくれるサービスです。

とりあえずやりたいことは、いまぽぴンち。でやっている、アソシエイト付のAmazonへのリンクを自動化したい。自動化というか動的に作成するまではしなくていいのだけど(どちらにしてもCGIは動かせないサーバなので)、現在手動でやっているHTML構築作業をプログラムにやらせたいなーと思って。

で、とりあえず組んでみたのが以下のコード。HttpWebRequestのサンプルまんまでちょっと恥ずかしいですが(エラーチェックもぜんぜんしてないし)AWSにアクセスしてXMLを取得、そこからDOM(Document Object Model)を作成するところまでなんとかできました。

  List<string> query = new List<string>();
  query.Add("AWSAccessKeyId=[この辺は表向きは書かないほうがいいかも]");
  query.Add("AssociateTag=popinchi-22");
  query.Add("Service=AWSECommerceService");
  query.Add("ResponseGroup=ItemAttributes%2CImages");
  query.Add("ItemPage=1");
  query.Add("Operation=ItemLookup");
  query.Add("ContentType=text%2Fxml");
  query.Add("IdType=ASIN");
  query.Add("Version=2005-10-05");
  query.Add("ItemId=" + textBox1.Text.Trim());    // textBox1にASINを入れる
  System.Net.HttpWebRequest req =
    (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(
      "http://webservices.amazon.co.jp/onca/xml?" +
      string.Join("&", query.ToArray()));
  System.Net.HttpWebResponse res = (HttpWebResponse)req.GetResponse();
  Stream st = res.GetResponseStream();
  StreamReader sr = new StreamReader(st, Encoding.UTF8);
  string html = sr.ReadToEnd();
  sr.Close();
  st.Close();
  System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
  doc.LoadXml(html);

ちなみにAWSからはこんな感じでXMLが返ってきます。ネタにするのは赤間本です(笑)。

<?xml version="1.0" encoding="UTF-8"?>
<ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
  <OperationRequest>
    <HTTPHeaders>
      <Header Name="UserAgent"></Header>
    </HTTPHeaders>
    <RequestId>1ETT01ZG824EZ6F9CG7K</RequestId>
    <Arguments>
      <Argument Name="AssociateTag" Value="popinchi-22"></Argument>
      <Argument Name="ItemId" Value="4891005157"></Argument>
      <Argument Name="ContentType" Value="text/xml"></Argument>
      <Argument Name="IdType" Value="ASIN"></Argument>
      <Argument Name="ItemPage" Value="1"></Argument>
      <Argument Name="Service" Value="AWSECommerceService"></Argument>
      <Argument Name="AWSAccessKeyId" Value="な・い・しょ"></Argument>
      <Argument Name="Version" Value="2005-10-05"></Argument>
      <Argument Name="ResponseGroup" Value="ItemAttributes,Images"></Argument>
      <Argument Name="Operation" Value="ItemLookup"></Argument>
    </Arguments>
    <RequestProcessingTime>0.0263030529022217</RequestProcessingTime>
  </OperationRequest>
  <Items>
    <Request>
      <IsValid>True</IsValid>
      <ItemLookupRequest>
        <IdType>ASIN</IdType>
        <ItemId>4891005157</ItemId>
        <ResponseGroup>ItemAttributes</ResponseGroup>
        <ResponseGroup>Images</ResponseGroup>
      </ItemLookupRequest>
    </Request>
    <Item>
      <ASIN>4891005157</ASIN>
      <DetailPageURL>http://www.amazon.co.jp/gp/(略)</DetailPageURL>
      <SmallImage>
        <URL>
          http://ec2.images-amazon.com/images/P/4891005157.01._SCTHUMBZZZ_V51803122_.jpg
        </URL>
        <Height Units="pixels">75</Height>
        <Width Units="pixels">58</Width>
      </SmallImage>
      <MediumImage>
        <URL>
          http://ec2.images-amazon.com/images/P/4891005157.01._SCMZZZZZZZ_V51803122_.jpg
        </URL>
        <Height Units="pixels">160</Height>
        <Width Units="pixels">123</Width>
      </MediumImage>
      <LargeImage>
        <URL>
          http://ec2.images-amazon.com/images/P/4891005157.01._SCLZZZZZZZ_V51803122_.jpg
        </URL>
        <Height Units="pixels">500</Height>
        <Width Units="pixels">383</Width>
      </LargeImage>
      <ImageSets>
        <ImageSet Category="primary">
          (上記SmallImage~LargeImageと同内容なので省略)
        </ImageSet>
      </ImageSets>
      <ItemAttributes>
        <Author>赤間 信幸</Author>
        <Binding>大型本</Binding>
        <Creator Role="著">赤間 信幸</Creator>
        <Label>日経BPソフトプレス</Label>
        <ListPrice>
        <Amount>3990</Amount>
        <CurrencyCode>JPY</CurrencyCode>
        <FormattedPrice>¥ 3,990</FormattedPrice>
        </ListPrice>
        <Manufacturer>日経BPソフトプレス</Manufacturer>
        <NumberOfPages>416</NumberOfPages>
        <PackageDimensions>
        <Length Units="cm">24</Length>
        </PackageDimensions>
        <ProductGroup>Book</ProductGroup>
        <PublicationDate>2006-05-18</PublicationDate>
        <Publisher>日経BPソフトプレス</Publisher>
        <Studio>日経BPソフトプレス</Studio>
        <Title>Microsoft Visual Studio 2005によるWebアプリケーション構築技法</Title>
      </ItemAttributes>
    </Item>
  </Items>
</ItemLookupResponse>

このXMLからこんな感じのイメージを出力したいわけです。こらそこっ、はてなダイアリーみたいとかいうなー!

ここまではなんとかなったのだけど、ここから先をどうするかというところでいろいろ考えていたり。

XmlDocument.LoadXmlメソッドでもってDOMツリーは構築できているのだけど、そのノードにそれぞれアクセスするのはどうするかニャーとか。とりあえずこういうコードを書いてみたけど、あまりにベタすぎて目から汗が出た orz

  System.Xml.XmlNode nodeItemLookupResponse = doc.ChildNodes[1];
  System.Xml.XmlNode nodeItems = nodeItemLookupResponse.ChildNodes[1];
  System.Xml.XmlNode nodeItem = nodeItems.ChildNodes[1];
  System.Xml.XmlNode nodeMediumImage = null;
  foreach (System.Xml.XmlNode node in nodeItem.ChildNodes)
  {
    if (node.Name == "MediumImage")
    {
      nodeMediumImage = node;
      break;
    }
  }
  if (nodeMediumImage != null)
  {
    System.Diagnostics.Debug.Print("URL:{0}", nodeMediumImage.ChildNodes[0].InnerText);
    System.Diagnostics.Debug.Print("Height:{0}", nodeMediumImage.ChildNodes[1].InnerText);
    System.Diagnostics.Debug.Print("Width:{0}", nodeMediumImage.ChildNodes[2].InnerText);
  }

これじゃあァァァんまりだァァアァ(エシディシ)ということで、ちょっと調査。SelectNodes/SelectSingleNodeメソッドを使うとXPathからノードが取れるとな!よーしよーしよし(ムツゴロウさん)なんとかなりそうだぜ…とこんなコードを書いてみた。

  System.Xml.XmlNode nodeMediumImage = doc.SelectSingleNode("/ItemLookupResponse/Items/Item/MediumImage");
  if (nodeMediumImage != null)
  {
    System.Diagnostics.Debug.Print("あったーよ!");
  }
  else
  {
    System.Diagnostics.Debug.Print("なかったズラ");
  }

しかし結果は「なかったズラ」一辺倒。うむむ、試しに適当に作ったXMLファイルだとうまく動いたりするので、何かが足りないらしい。

動かない原因を調べてみたところ、ItemLookupResponseのxmlnsが付いていると検索できないっぽいです。XMLについては素人の私ですが、とりあえずネームスペース関係らしいことぐらいはわかります。かと言って、なぜこのネームスペース指定があると検索できないのかまではさっぱりわからず。勉強不足ですね orz

それで今日一日調べていたのですけど(ヒマですね)どうやらこんな感じでやればイケるみたいです。要はXmlNameManagerクラスを作って、そこにAddNamespaceメソッドで別名を定義、選択時はその別名をつけて検索せよと。

参考:@IT:連載:.NETで簡単XML 第5回 DOMとXPath

  System.Xml.XmlNamespaceManager nsManager = new System.Xml.XmlNamespaceManager(doc.NameTable);
  nsManager.AddNamespace("aws", "http://webservices.amazon.com/AWSECommerceService/2005-10-05");
  nodeMediumImage = doc.SelectSingleNode(
    "/aws:ItemLookupResponse/aws:Items/aws:Item/aws:MediumImage", nsManager);
  if (nodeMediumImage != null)
  {
    System.Xml.XmlNode nodeValue;
    System.Xml.XmlNode nodeAttrib;
    nodeValue = nodeMediumImage.SelectSingleNode("aws:URL/text()", nsManager);
    System.Diagnostics.Debug.Print("URL:{0}", node.Value);
    nodeValue = nodeMediumImage.SelectSingleNode("aws:Width/text()", nsManager);
    nodeAttrib = nodeMediumImage.SelectSingleNode("aws:Width/@Units", nsManager);
    System.Diagnostics.Debug.Print("Width:{0}{1}", nodeValue.Value, nodeAttrib.Value);
    nodeValue = nodeMediumImage.SelectSingleNode("aws:Height/text()", nsManager);
    nodeAttrib = nodeMediumImage.SelectSingleNode("aws:Height/@Units", nsManager);
    System.Diagnostics.Debug.Print("Height:{0}{1}", nodeValue.Value, nodeAttrib.Value);
  }
  else
  {
    System.Diagnostics.Debug.Print("なかったズラ");
  }

と、これでとりあえずは取得できることが判明したわけで、また一歩野望に近づいた!(何の野望だ)。

続きは気が向いたら書くことにします。

投稿日時 : 2007年1月7日 18:53

Feedback

# re: XMLでごにょごにょ 2007/01/07 22:03 アクア

早く気が向きますように…

# re: XMLでごにょごにょ 2007/01/07 23:27 backdoor

この辺りの実装技術は専門外なのでその方面のコメントはできません。(申し訳ない)

ただ、他のわんくまメンバーの技術情報にはあまり見られない試行錯誤ストーリーを感じることができたので(私的には)好みのタイプです。
# 変な誤解しないこと! こことても重要。

ぽぴ王子らしさを感じる内容に好感度up、これからも頑張って下さい。

# re: XMLでごにょごにょ 2007/01/08 14:28 かるあ

あれ? wsdl から proxy クラスの自動生成は使わないで組んでみようってことですか?

# 思いっきりはずしている予感

# re: XMLでごにょごにょ 2007/01/09 10:29 ぽぴ王子

■アクアさん
気が向いたらもう少し煮詰めて、ASINコードを入れたらHTMLを作成してくれるツールを作ろうと思っています(あくまで自分専用ですが)。
いつ気が向くかは私にもわかりません(笑)
その時はまたこんな感じで書いてみようかと。

■backdoorさん
そういえばみなさん試行錯誤って書かれてませんよね。
してるとは思うのだけど、書くのが面倒だからなのかな。
僕としては、それまでの工程が意外と資料になりうるのではないかと思うので、こんな感じで書いてみました。ネームスペース関係で一日つぶしていろいろ調べてたのだけど、そこをもう少し書いてみればよかったなとかちょっと後悔もしてますが。

■かるあさん
そんな難しいこと言わないでください :-)
wsdlって初めて聞きましたわ。ちょっと調べたけど、なんか難しそう…
SOAPとかわからないからあえてRESTに逃げた私(ぉぃ)にそんなの振られても!! ○| ̄|_

# re: XMLでごにょごにょ 2007/01/09 13:07 刈歩 菜良

RESTの方がむっちゃくちゃふくざつだったりするんよ。

WSDL使うんやったら自分のアプリのソリューションに[Web参照の追加]ってやって、WebサービスのURLを入れるだけ。そうするとプロキシークラスってのが生成されて、それを使うだけで、簡単にWebサービスにアクセスできちゃう。
SOAPの知識なんかなぁ~んもいらん。

お試しあれ。

# re: XMLでごにょごにょ 2007/01/09 13:40 ぽぴ王子

Ω<な、なんやてー?!
(あえて「焼きたて!!ジャぱん」風に)

ちょっとテストしてみました。
うおー、ホントだーっ!すっげー!

.NETにこだわるつもりもなく、とりあえずRESTでリクエスト投げて帰ってきたXMLを解析すればいろいろ遊べるよねーって感じでいたんで、こんなことができるとは知りませんでしたよ。

逆に「知識なんかなぁ~んもいらん」だと勉強にならないかなぁとか思った王子。天邪鬼ですいますん。
参考:http://www.atmarkit.co.jp/fdotnet/dotnettips/298aspamazonsvc/aspamazonsvc.html

# re: XMLでごにょごにょ 2007/01/09 15:50 刈歩 菜良

> 逆に「知識なんかなぁ~んもいらん」だと勉強にならないかなぁとか思った王子。天邪鬼ですいますん。

いやいや、全然天邪鬼だなんてとんでもない!!
その通りっ!っすよ。

業務上XMLを直接ごにょごにょする必要がなく、かつ、王子のように自力で勉強しようという気概もなく...
VSさんにおんぶにだっこでございます。
(T_T)

そういやぁ。VS2005になってからプロキシクラスのソースが見当たらんようになった。VS2003の時は[すべてのファイルを表示]だっけかな?そんなんでソースを見れたんやが。
キチンと本気で探してないのでなんかやり方があるんやと思うけど。

# re: XMLでごにょごにょ 2007/01/09 17:50 Hirotow

>プロキシクラスのソース
<プロジェクトディレクトリ>\Web References\<参照名>\Reference.csにあります。
ちなみにプロキシクラスを使ったときに直にXMLを取得する手段はあるのでしょうか?

# re: XMLでごにょごにょ 2007/01/10 10:09 刈歩 菜良

Hirotowさん

あ、ほんとだ!
なんでだろ?勘違いしてました。
VSからも[すべてのファイルを表示]で
Web References→<参照名>→Reference.map→Reference.cs
で見れました。

きちんと確認も取らずうそ言ってごめんなさい。>王子、ご覧の皆様

# re: XMLでごにょごにょ 2007/01/10 10:30 刈歩 菜良

もとい!

WebアプリからWeb参照してみたら、やっぱプロキシクラスのソースが見当たりませんでした。
で、探してみたら
<OSのフォルダ>→Microsoft.NET→Temporary ASP.NET Files→<Webアプリ名>→<ごにょごにょなフォルダ名>→<ごにょごにょなフォルダ名>→Sources_App_WebReferences
の下にございました。

VS2005になってから(というか、ASP.NET 2.0になってから)aspxファイルから自動生成されるコードがソリューション上に見えなくなりましたよね。
それと同じ理由でプロキシークラスのソースも位置が変わったのかと...

# 東京勉強会 #5の話 2007/01/29 14:54 ぽぴ王子の人生プログラミング中

東京勉強会 #5の話

# Let's nore R6を買った 2007/08/02 0:11 ぽぴ王子の人生プログラミング中

Let's nore R6を買った

# Let's nore R6を買った 2007/08/02 6:33 ぽぴ王子の人生プログラミング中

Let's nore R6を買った

タイトル
名前
Url
コメント