1. 概要
「.xml」ファイルを扱ってみようと思いましたら、組込のライブラリにこれがあるそうで・・・。
2. 単純に読んで出力してみる
参考サイトのまま(少し訂正すべき個所がありましたが)に書いてみました。
こういう内容の(前半のみ掲載)「.xml」ファイルがあります。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE urlset>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://freebsd.sing.ne.jp/</loc> <lastmod>2018-10-10</lastmod><changefreq>monthly</changefreq><priority>0.3</priority></url> <!-- トップ -->
<url><loc>https://freebsd.sing.ne.jp/00/</loc> <lastmod>2018-10-30</lastmod><changefreq>monthly</changefreq><priority>0.1</priority></url> <!-- 共通 -->
<url><loc>https://freebsd.sing.ne.jp/01/08.04/</loc> <lastmod>2015-06-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 8.4 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/09.03</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 9.3 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/10.02/</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 10.2 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/11.00/</loc> <lastmod>2017-11-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 11.0 RELEASE -->
入力したファイルをそのまま出力したらどうなるのかをやってみました。
require('pry')
require('rexml/document')
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
file = File.open('old.xml')
doc = REXML::Document.new(file)
File.write('new01.xml', doc)
というソースを書いて実行した結果、こういう形で出力されました。
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE urlset><urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>
<url><loc>https://freebsd.sing.ne.jp/</loc> <lastmod>2018-10-10</lastmod><changefreq>monthly</changefreq><priority>0.3</priority></url> <!-- トップ -->
<url><loc>https://freebsd.sing.ne.jp/00/</loc> <lastmod>2018-10-30</lastmod><changefreq>monthly</changefreq><priority>0.1</priority></url> <!-- 共通 -->
<url><loc>https://freebsd.sing.ne.jp/01/08.04/</loc> <lastmod>2015-06-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 8.4 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/09.03</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 9.3 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/10.02/</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 10.2 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/11.00/</loc> <lastmod>2017-11-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 11.0 RELEASE -->
<url><loc>https://freebsd.sing.ne.jp/01/10.03/</loc> <lastmod>2018-04-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 10.3 RELEASE -->
実は、微妙な違いはあるのですが、意味合い的にはまったく同じものが出力されることが確認できました。
しめしめ。
最終目的で、ある個所を編集するのを自動でやるのはできそうです。
3. 要素を取得する
要素を取得するには、「elements」というメソッドを使えばいいらしいので。
require('pry')
require('rexml/document')
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
file = File.open('old.xml')
doc = REXML::Document.new(file)
doc.elements['urlset/url'].each do | url |
puts("url=[#{url}]")
end
というソースを書いて実行したら、こんなんなっちゃいまして。
url=[<loc>https://freebsd.sing.ne.jp/</loc>]
url=[ ]
url=[<lastmod>2018-10-10</lastmod>]
url=[<changefreq>monthly</changefreq>]
url=[<priority>0.3</priority>]
each で全要素を取得する予定だったのですが、これはどうも使い方が悪かったようで。
[''] で指定したものは、先頭の要素しか取り出せないようです。
参考サイトを読んで、使い方がわかりました。
require('pry')
require('rexml/document')
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
file = File.open('old.xml')
doc = REXML::Document.new(file)
doc.elements.each('urlset/url') do | url |
puts("url=[#{url}]")
end
というソースを書いて実行した結果、以下の結果が得られました(途中までしか出力していません)。
url=[<url><loc>https://freebsd.sing.ne.jp/</loc> <lastmod>2018-10-10</lastmod><changefreq>monthly</changefreq><priority>0.3</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/00/</loc> <lastmod>2018-10-30</lastmod><changefreq>monthly</changefreq><priority>0.1</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/01/08.04/</loc> <lastmod>2015-06-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/01/09.03</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/01/10.02/</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/01/11.00/</loc> <lastmod>2017-11-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/01/10.03/</loc> <lastmod>2018-04-30</lastmod><changefreq>never</changefreq><priority>0.0</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/10.04/</loc> <lastmod>2018-01-22</lastmod><changefreq>yearly</changefreq><priority>0.2</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/11.01/</loc> <lastmod>2018-07-18</lastmod><changefreq>monthly</changefreq><priority>0.3</priority></url>]
url=[<url><loc>https://freebsd.sing.ne.jp/11.02/</loc> <lastmod>2018-10-15</lastmod><changefreq>monthly</changefreq><priority>0.4</priority></url>]
要素内の要素を取り出すのはこの応用になるようで
require('pry')
require('rexml/document')
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
file = File.open('old.xml')
doc = REXML::Document.new(file)
doc.elements.each('urlset/url') do | url |
puts("loc=[#{url.elements['loc']}] lastmod=[#{url.elements['lastmod']}] lastmod.text=[#{url.elements['lastmod'].text}]")
end
というソースを書いて実行した結果、以下の結果が得られました(途中までしか出力していません)。
loc=[<loc>https://freebsd.sing.ne.jp/</loc>] lastmod=[<lastmod>2018-10-10</lastmod>] lastmod.text=[2018-10-10]
loc=[<loc>https://freebsd.sing.ne.jp/00/</loc>] lastmod=[<lastmod>2018-10-30</lastmod>] lastmod.text=[2018-10-30]
loc=[<loc>https://freebsd.sing.ne.jp/01/08.04/</loc>] lastmod=[<lastmod>2015-06-30</lastmod>] lastmod.text=[2015-06-30]
loc=[<loc>https://freebsd.sing.ne.jp/01/09.03</loc>] lastmod=[<lastmod>2016-12-31</lastmod>] lastmod.text=[2016-12-31]
loc=[<loc>https://freebsd.sing.ne.jp/01/10.02/</loc>] lastmod=[<lastmod>2016-12-31</lastmod>] lastmod.text=[2016-12-31]
loc=[<loc>https://freebsd.sing.ne.jp/01/11.00/</loc>] lastmod=[<lastmod>2017-11-30</lastmod>] lastmod.text=[2017-11-30]
loc=[<loc>https://freebsd.sing.ne.jp/01/10.03/</loc>] lastmod=[<lastmod>2018-04-30</lastmod>] lastmod.text=[2018-04-30]
loc=[<loc>https://freebsd.sing.ne.jp/10.04/</loc>] lastmod=[<lastmod>2018-01-22</lastmod>] lastmod.text=[2018-01-22]
loc=[<loc>https://freebsd.sing.ne.jp/11.01/</loc>] lastmod=[<lastmod>2018-07-18</lastmod>] lastmod.text=[2018-07-18]
loc=[<loc>https://freebsd.sing.ne.jp/11.02/</loc>] lastmod=[<lastmod>2018-10-15</lastmod>] lastmod.text=[2018-10-15]
4. 要素を更新する
前項までの内容を踏まえて。
要素を更新するには「elements.text」を書き変えればいいらしい。
require('pry')
require('rexml/document')
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
file = File.open('old.xml')
doc = REXML::Document.new(file)
doc.elements.each('urlset/url') do | url |
if (url.elements['loc'].text == 'https://freebsd.sing.ne.jp/01/10.02/')
url.elements['lastmod'].text = '2018-11-13'
end
end
File.write('new02.xml', doc)
というソースを書いて、最初に出力した .xml ファイルとの diff をとると
8c8
< <url><loc>https://freebsd.sing.ne.jp/01/10.02/</loc> <lastmod>2016-12-31</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 10.2 RELEASE -->
---
> <url><loc>https://freebsd.sing.ne.jp/01/10.02/</loc> <lastmod>2018-11-13</lastmod><changefreq>never</changefreq><priority>0.0</priority></url> <!-- 10.2 RELEASE -->
と思い通りの結果が得られました。
5. 参考サイト
本ページは、下記のサイトを参考にさせていただきました。
「library rexml/document (Ruby 2.5.0)」
「RubyからXMLファイルを動的に編集する」
「Ruby で xml ファイル読み込みを行う方法:rexml」(2026年2月25日、リンク切れになっています)