NokogoriでのXMLパース


 最近久しぶりにrubyをよく書いてます(デジャヴ)。
xmlを解析するだけの簡単なお仕事。なので、Nokogiri使い始めたのですけど、

P.S. 正確にはNokogoriでのXML/HTMLパースでした><


2点ほど罠があったんでメモっときます。

XML名前空間*1


分からなくて最初は、xml.xpath("//div")とかしても、そこにあるはずなのに引っかからないと、半日くらいはまりました><


解析したいXMLに以下の感じで、のようにxmlnsの指定がある場合は

<Vulnerability xmlns="http://www.icasi.org/CVRF/schema/vuln/1.1" Ordinal="86097">
<Title>CVE-2016-0001</Title>
<Notes><Note Type="Description" Ordinal="1">** RESERVED **
This candidate has been reserved by an organization or individual that
will use it when announcing a new security problem.  When the
candidate has been publicized, the details for this candidate will be
provided.
</Note>
</Notes>
<CVE>CVE-2016-0001</CVE>
</Vulnerability>


以下のような、XPathは駄目で、

xml_doc.xpath(".//Notes")


以下のように、namespaceを指定してやらないと見つけてくれないです (´・ω・`)

namespaces = {
  "ns" => "http://www.icasi.org/CVRF/schema/vuln/1.1"
}
xml_doc.xpath(".//ns:Notes", namespaces)

tbody要素の混入(Chromeを用いた場合)*2


Rubyクローラ本にはXPathの簡単な取得方法として、FirefoxChromeのブラウザを使う方法が乗ってるのですがChromeには、はまりポイントがありました。
Chromeでの検証(Ctrl+Shift+I)等から、選択した要素のXPathを取得するのですが取得したXPathに、よく*3tbody要素が混入してくれやがりますヾ(`Д´*)ノ


Chromeから普通にXPathのコピペした場合に、以下のようにtbodyが混入している場合は駄目で

html_doc.xpath('//*[@id="hoge"]/table/tbody/tr')


以下のようにtbody要素を削除してやらないと、正確でないため見つけてくれませんでしたよ、 わっしょい(┘´▽`)┘~┻┻

html_doc.xpath('//*[@id="hoge"]/table/tr')

まとめ


ひとまず以下のRubyクローラ本読みながら、四苦八苦してます。(書くのはjson/yaml等に比べてメンドクサそうだけど、まあ提供されるXMLのパースは楽っぽいのか?

*1:Rubyクローラ本では「3-4-5 RSS/Atomの解析」のP.168 辺りに記載

*2:Rubyクローラ本では「3-5-4 簡単なXPathの抽出方法」のP.183 辺りに記載

*3:table近辺に