[ruby-list:41856] Re: rexml で doc.xml_decl.encoding = "shift-jis" は駄目ですか?

From: take_tk <ggb03124@...>
Date: 2006-02-25 03:02:17 UTC
List: ruby-list #41856
たけ(tk)です。

[ruby-list:41855] Re: rexml で doc.xml_decl.encoding = "shift-jis" は駄
目ですか? にて 
Kouhei Sutou <kou@cozmixng.org> さん 曰く:

> よく覚えていませんが,REXMLの内部エンコーディングはUTF-8なの
> で値を設定するときはdoc.xml_decl.encodingに関わらずUTF-8で指
> 定しなければいけなかった気がします.

いろいろと複雑でしたが、次のようにまとめられそうです。

まず、NKFとUconvとの関係について
(なお UconvとIconvとでは、このデータでは同じになった)、

(1)NKF.nkf("-u","一覧表")で変換したutf文字列と、Uconv.sjistou8( "一覧
表" )とで変換した文字列とでは異なる。

(2)NKF.nkf("-u","一覧表")で変換したutf文字列を NKF.nkf("-s",utf8)で戻
すのはOK、Uconv.sjistou8( "一覧表" )をUconvで戻すのはOK。

(3)Uconv.sjistou8( "一覧表" )をNKF.nkf("-s",utf8)で戻すのはOKだが、
(4)NKF.nkf("-u","一覧表")で変換したutf文字列をUconvで戻すのは失敗する。

REXMLはUconvで変換しているのだが・・、

(5)REXMLではUconvでutf8からsjisに変換しようとするので、NKFでutf8に変
換したutf8文字列をセットすると、失敗する。

(6)REXMLはDocument#to_sでは変換しようとするが、Element#to_s や 
Attribute#to_s では変換しない。

* REXML は $KCODE を見て内部で変換すべきである。
C:/Program Files/Apollo/lib/ruby/1.8/rexml/encodings/SHIFT-JIS.rb には 
decode メソッドも用意されているのだから、あとちょっとで実現できるはず。

(7)対症療法としては、入力値をUconvでutf8に変換すればOK。

* REXML の inspect はどうにかして欲しい。クラス名がでないので役に立た
ない・・。

----
#! ruby -Ks

  require "iconv"
  class Iconv
    def self.sjis_to_utf8(str)
      Iconv.iconv("utf-8", "shift_jis", str).join('')
    end
    def self.utf8_to_sjis(str)
      Iconv.iconv("shift_jis", "utf-8", str).join('')
    end
  end

  require 'uconv'
  module Uconv
    def self.sjis_to_utf8(str)
      Uconv.sjistou8( str )
    end
    def self.utf8_to_sjis(str)
      Uconv.u8tosjis( str )
    end
  end

  require "nkf"
  module NKF
    def self.sjis_to_utf8(str)
      NKF.nkf('-u', str )
    end
    def self.utf8_to_sjis(str)
      NKF.nkf('-s', str )
    end
  end

#(1)NKF.nkf("-u","一覧表")で変換したutf文字列と、Uconv.sjistou8( "一覧
#表" )とで変換した文字列とでは異なる。

p NKF.sjis_to_utf8('一覧表')    #=> "\e$B0lMwI=\e(B"
p Uconv.sjis_to_utf8('一覧表')  #=> "荳\200隕\247陦\250"

#(2)NKF.nkf("-u","一覧表")で変換したutf文字列を NKF.nkf("-s",utf8)で戻
#すのはOK、Uconv.sjistou8( "一覧表" )をUconvで戻すのはOK。

p NKF.utf8_to_sjis(NKF.sjis_to_utf8('一覧表'))     #=> "一覧表"
p Uconv.utf8_to_sjis(Uconv.sjis_to_utf8('一覧表')) #=> "一覧表"

#(3)Uconv.sjistou8( "一覧表" )をNKF.nkf("-s",utf8)で戻すのはOKだが、
#(4)NKF.nkf("-u","一覧表")で変換したutf文字列をUconvで戻すのは失敗する。

p NKF.utf8_to_sjis(Uconv.sjis_to_utf8('一覧表'))   #=> "一覧表"
p Uconv.utf8_to_sjis(NKF.sjis_to_utf8('一覧表'))   #=> "\e$B0lMwI=\e(B"
----

----
#! ruby -Ks
require "rexml/document"
require "nkf"
require 'uconv'

doc = REXML::Document.new
doc.xml_decl.encoding = "shift-jis"
doc.add_element("pxd")

#(6)REXMLはDocument#to_sでは変換しようとするが、Element#to_s や 
#Attribute#to_s では変換しない。

doc[1].attributes["name"] = "一覧表"
puts doc[1].attributes["name"] #=> 一覧表
puts doc[1]                    #=> <pxd name='一覧表'/>
#puts doc                       #=> illegal UTF-8 sequence (88) (Uconv::Error)
#                             ↓

#(4)NKF.nkf("-u","一覧表")で変換したutf文字列をUconvで戻すのは失敗する。
#(5)REXMLではUconvでutf8からsjisに変換しようとするので、NKFでutf8に変
#換したutf8文字列をセットすると、失敗する。

doc[1].attributes["name"] = NKF.nkf("-u","一覧表")
puts doc[1].attributes["name"] #=> 一覧表
puts doc[1]                    #=> <pxd name='一覧表'/>
puts doc                       #=> <?xml version='1.0' encoding='SHIFT-JIS'?><pxd name='一覧表'/>
#                             ↓

#(2)Uconv.sjistou8( "一覧表" )をUconvで戻すのはOK。
#(6)REXMLはDocument#to_sでは変換しようとするが、Element#to_s や 
#Attribute#to_s では変換しない。

doc[1].attributes["name"] = Uconv.sjistou8("一覧表")
puts doc[1].attributes["name"] #=> 荳hヲァ陦ィ
puts doc[1]                    #=> <pxd name='荳hヲァ陦ィ'/>
puts doc                       #=> <?xml version='1.0' encoding='SHIFT-JIS'?><pxd name='一覧表'/>

p :ok
----

take_tk = kumagai hidetake

In This Thread