356


Rubyのバージョンは2.1.2です。

REXMLを使ってXML内の特定のタグ以下のノードにマッチさせたいです。  
タグが英語であればマッチするのですが、日本語のタグだとルート以下の全体がマッチしてしまいます。  
例えば、XML解析のRubyコードは以下のようになっています。

[code]

    require 'rexml/document'
    
    doc = nil
    File.open("example.xml") do |file|
      doc = REXML::Document.new(file)
    end
    
    puts REXML::XPath.match(doc, "/root/a")
    
[/code]

この時、読み込むexample.xmlが以下のような場合は、

[code]

    <?xml version="1.0" ?>
    <root>
      <a>
        <b/>
      </a>
      <a>
        <b>bbb1</b>
        <b>bbb2</b>
          <e>eeee1</e>
          <f>ffff1</f>
        <b>bbb3</b>
        <c>ccc1</c>
      </a>
      <a>
        <b>bbb4</b>
        <b>bbb5</b>
      </a>
    </root>
    
[/code]

以下のように返ってきますが、

[code]

    #<a>
    #  <b/>
    #</a>
    #<a>
    #  <b>bbb1</b>
    #  <b>bbb2</b>
    #    <e>eeee1</e>
    #    <f>ffff1</f>
    #  <b>bbb3</b>
    #  <c>ccc1</c>
    #</a>
    #<a>
    #  <b>bbb4</b>
    #  <b>bbb5</b>
    #</a>
    
[/code]

example.xmlが以下のような場合、

[code]

    <?xml version="1.0" ?>
    <本棚>
      <本>
        <b/>
      </本>
      <本>
        <b>bbb1</b>
        <b>bbb2</b>
          <e>eeee1</e>
          <f>ffff1</f>
        <b>bbb3</b>
        <c>ccc1</c>
      </本>
      <本>
        <b>bbb4</b>
        <b>bbb5</b>
      </本>
    </本棚>
    
[/code]

Rubyのコードを以下のように書き換えても、

[code]

    # coding: utf-8
    require 'rexml/document'
    
    doc = nil
    File.open("example.xml") do |file|
      doc = REXML::Document.new(file)
    end
    
    puts REXML::XPath.match(doc, "/本棚/本")
    
[/code]

以下のように返ってきます。

[code]

    #<本棚>
    #  <本>
    #    <b/>
    #  </本>
    #  <本>
    #    <b>bbb1</b>
    #    <b>bbb2</b>
    #      <e>eeee1</e>
    #      <f>ffff1</f>
    #    <b>bbb3</b>
    #    <c>ccc1</c>
    #  </本>
    #  <本>
    #    <b>bbb4</b>
    #    <b>bbb5</b>
    #  </本>
    #</本棚>
    
[/code]

理想は以下のように返ってきて欲しいです。

[code]

    #<本>
    #  <b/>
    #</本>
    #<本>
    #  <b>bbb1</b>
    #  <b>bbb2</b>
    #    <e>eeee1</e>
    #    <f>ffff1</f>
    #  <b>bbb3</b>
    #  <c>ccc1</c>
    #</本>
    #<本>
    #  <b>bbb4</b>
    #  <b>bbb5</b>
    #</本>
    
[/code]

XMLファイル自体の文字コードはUTF-8です。 どのようにしたら希望通りにパースされた結果を得ることができるでしょうか？


CC BY-SA 3.0
2014-12-04T07:43:08.540
352
2014-12-10T06:27:06.527
2014-12-10T06:27:06.527
982
192
question
ruby xml xpath
XPathでXMLの要素名に日本語が使われている要素をマッチさせたい


nokogiriでもよろしければ

[code]

    require 'nokogiri'
    
    doc = nil
    File.open("example.xml") do |file|
       doc = Nokogiri::XML(file)
    end
    
    puts doc.xpath("/本棚/本")
    
[/code]

で、以下の様に取得できました。

[code]

    <本>
        <b/>
        </本>
    <本>
          <b>bbb1</b>
          <b>bbb2</b>
          <e>eeee1</e>
          <f>ffff1</f>
          <b>bbb3</b>
          <c>ccc1</c>
        </本>
    <本>
          <b>bbb4</b>
          <b>bbb5</b>
        </本>
    
[/code]

以下の環境で確認しました

  * windows 7 + ruby 2.1.4 + nokogiri 1.6.5

  * Ubuntu 14.04 + ruby 2.1.5 + nokogiri 1.6.5  
( ruby2.1-dev, libxml2, libxml2-dev, libxslt1.1, libxslt1-dev )

* * *

## 補足の追記:

いきなりnokogoriを提案した形になってしまったので少し補足します。 ubuntuやwindows上でもREXMLでは"/本棚/本"が "/本棚"
と同じ動きになっていました。
また、"/山/川"などとしても同様に"/山"と同じ様な動作でしたのでnokogiriで試してみたら上手くいったので提案しました。

ruby
1.8をつかって日本語でも正しく区切られるようなページを見かけていたため、先ほど気になって試してみましたが、windows環境でrubyinstallerからruby
1.8.7を入れて質問のrexmlで"/本棚/本"のソースそのままで試したところ以下の様に取得されました。  
※
1.8.7でコマンドプロンプト上で実行するとコマンドプロンプトがutf8をプリントできずに`本`が`<譛ｬ>`と化けてしまいますが、ファイルにリダイレクトすればutf8の文字コードで以下の内容になっています。

[code]

    <本>
        <b/>
        </本>
    <本>
          <b>bbb1</b>
          <b>bbb2</b>
          <e>eeee1</e>
          <f>ffff1</f>
          <b>bbb3</b>
          <c>ccc1</c>
        </本>
    <本>
          <b>bbb4</b>
          <b>bbb5</b>
        </本>
    
[/code]

問題は Win/Linuxどちらでも起きているので、rubyかREXMLかどちらかのバージョンの問題と思われます。


CC BY-SA 3.0
2014-12-04T14:07:45.797
356
2014-12-05T04:08:52.260
2014-12-05T04:08:52.260
728
728
352
answer