Hatena::Grouprubyist

今日も元気にrubyist

2007-05-30

REXML 昨日の続き 17:11 REXML 昨日の続き - 今日も元気にrubyist を含むブックマーク はてなブックマーク - REXML 昨日の続き - 今日も元気にrubyist REXML 昨日の続き - 今日も元気にrubyist のブックマークコメント

昨日のエントリで「REXMLを使うときにはクラスに注意しましょう」みたいなことを書いたが、基本は

require 'kconv'
require 'rexml/document'
include REXML

doc = REXML::Document.new File.open("newsing.xml","r")
p doc.class #=> REXML::Document
p doc.root.class #=> REXML::Element

REXML::Documentクラスを生成した後、rootメソッドをつけてDOMツリーの一番上から要素を指定してやればよいみたい。

RubyでXML操作 | Netsphere Laboratories

XMLのサンプルは昨日の日記参照。…データがちょっと違うけど構成は一緒なのでまぁ察してください(´ー`)

puts doc.root.elements[1].elements[1].class
 #=> REXML::Element
puts doc.root.elements[1].elements[1].text.tosjis
 #=> http://newsing.jp/entry?url=www.shopjapan.co.jp%2Fbillysbootcamp%2F%3Faf_id%3D23%26banner_id%3Dya_00164
puts doc.root.elements[1].elements[2].text.tosjis
 #=> うわさのビリーはよく見ると " ET " みたい
puts doc.root.elements[1].elements[3].text.tosjis
 #=> undefined method `tosjis' for nil:NilClass (NoMethodError)

空要素の時はエラーとなるので条件分岐を入れなければいけない。

p doc.root.elements[1].elements[3].has_text?
 #=> false
puts doc.root.elements[1].elements[3].text.tosjis if doc.root.elements[1].elements[3].has_text?
 #=> 何も出力されない

ちなみにREXML::Elements#[index, name=nil]という形で「nameという要素名を持つindex番目の要素」を返せる。

が、今回使うXMLのように全ての要素名がユニークな時には使う意味はない。逆に

<?xml version="1.0" encoding="Shift-JIS" standalone="yes"?>
<items>
  <item>
    <url>http://newsing.jp/entry?url=www.shopjapan.co.jp%2Fbillysbootcamp%2F%3Faf_id%3D23%26banner_id%3Dya_00164</url>
    <title>うわさのビリーはよく見ると &quot; ET &quot; みたい</title>
    <comment>コメント1</comment>
    <comment>コメント2</comment>
    <comment>コメント3</comment>
    <comment>コメント4</comment>
  </item>
</items>

みたいなフラットXMLなら「X番目のコメントを取り出す」とかに使えて便利。

XPATHでやる

以上がindex番号による指定で、当然XPATHでも指定できる。

puts doc.root.elements[1].elements["url"].text.tosjis
 #=> http://newsing.jp/entry?url=www.shopjapan.co.jp%2Fbillysbootcamp%2F%3Faf_id%3D23%26banner_id%3Dya_00164
puts doc.root.elements[1].elements["title"].text.tosjis
 #=> うわさのビリーはよく見ると " ET " みたい
puts doc.root.elements[1].elements["main_text"].text.tosjis
 #=> undefined method `tosjis' for nil:NilClass (NoMethodError)

後から要素が追加される可能性を考えると、こっちの方が賢そう。

指定した要素全てを抜き出す

each(ブロック)を使わずXMLの指定した要素を全て取り出す方法はいろいろ調べたけどないっぽい。残念

REXML::Elements#[xpath]
xpathに最初にマッチした子要素を返す。

XPATHで見つかった要素全てを配列で返してくれるとかだったら良かったのに。

仕方がないのでブロック

require 'kconv'
require 'rexml/document'
include REXML

doc = REXML::Document.new File.open("newsing.xml","r")

# 1.基本形
doc.root.each_element do |elem|
  puts elem.elements["title"].text.tosjis
end

# 2.回数を指定する場合
doc.root.each_element_with_text(nil, 10) do |elem|
  puts elem.elements["title"].text.tosjis
end

# 3.XPATHでダイレクト指定
doc.elements.each("//title") do |elem|
  puts elem.text.tosjis
end

# 4.uptoでごり押し
1.upto(10) do |i|
  entry = doc.root.elements[i]
  puts entry.elements["title"].text.tosjis
end

結果は全部同じ。#each_element_with_textが回数指定できて、#each_elementはできないってのが疑問だけど仕方ない。それぞれの方法に得手不得手があるから目的に合わせて使い分ければいいんじゃないかな(・ω・)人(・ω・)

textとget_text

get_textメソッドを使うとREXML::Textクラスで抽出し、特殊文字実体参照に変換してくれる。

require 'kconv'
require 'rexml/document'
include REXML

doc = REXML::Document.new File.open("newsing.xml","r")

puts doc.root.elements["//title"].text.class
 #=> String
puts doc.root.elements["//title"].text.tosjis
 #=> うわさのビリーはよく見ると " ET " みたい
puts doc.root.elements["//title"].get_text.class
 #=> REXML::Text
puts doc.root.elements["//title"].get_text.to_s.tosjis
 #=> うわさのビリーはよく見ると &quot; ET &quot; みたい
puts doc.root.elements["//title"].get_text.tosjis
 #=> undefined method `tosjis' for #<REXML::Text:0x2ba54d0> (NoMethodError)

普通エスケープすればよいのであまり使わないかな…。

DennisedispDennisedisp2017/03/29 14:23flagyl bijwerkingen hond
<a href= http://masonducay.over-blog.com/2017/03/zovirax.html >zovirax creme tijdens zwangerschap</a>
<a href=http://masonducay.over-blog.com/2017/03/zovirax.html>zovirax cream baby</a>
zovirax oogzalf aciclovir
<a href= http://lonsibounm.eklablog.net >overdosis propranolol dodelijk</a>
<a href=http://masonducay.over-blog.com/2017/03/zovirax.html>zovirax creme 2g prix</a>
propranolol en angststoornissen

WilliamfenWilliamfen2017/03/31 16:57aknemycin plus lösung erfahrungsberichte
<a href= http://bobbicraws.site123.me/about >resochin 250</a>
<a href=https://agnusdinap.yolasite.com>nifurantin und pille</a>
azithromycin 500 n2
<a href= http://bobbicraws.site123.me/about >resochin malaria tropica</a>
<a href=https://benitocape.jimdo.com>aknemycin lösung</a>
nifurantin b6 nebenwirkungen

ReubenhopReubenhop2017/04/02 22:29augmentin serve gastroprotettore
<a href= http://www.onweb.fr?company_id=17318 >pilula qlaira engorda</a>
<a href=http://www.onweb.fr?company_id=17318>qlaira preço panvel</a>
diclofenaco potássico gotas
<a href= http://janethorua.guildomatic.com >augmentin 500mg/62 5 mg</a>
<a href=http://laureneasu.tribalpages.com>diclofenaco pomada na gravidez</a>
albendazol dose unica posologia

MatthewDakMatthewDak2017/04/07 14:15amoxicilline sandoz 1g
<a href= http://sydneyvoll.webblogg.se >tolexine gé 100 avis</a>
<a href=http://salomemahe.page4.me>finasteride generique biogaran</a>
prix doxyval 250 mg
<a href= http://gitabeursk.site123.me/about >dermipred 10 posologie chat</a>
<a href=http://sydneyvoll.webblogg.se>tolexine 100 mg</a>
dermipred 10 20

JamesvorJamesvor2017/04/10 15:43zovirax compresse posologia
<a href= http://kirkagrest.myfreesites.net >etoricoxib generico prezzo</a>
<a href=http://karlbiasot.yolasite.com>janumet 50mg/1000mg</a>
amoxicillina generico prezzo
<a href= http://www.onweb.fr?company_id=17319 >amoxicillina generico di</a>
<a href=http://www.luciocapsh-87.webself.net>sandoz-celecoxib 200 mg</a>
etoricoxib nombre generico