Top / PHP / Liblary / SPL / SimpleXML / mb_convert_encoding


 #setlinebreak(on)
 * SJIS、EUC-JP、JISなどの日本語をSimpleXMLで使う方法 [#i74ad925]
 #htmlinsert(googleAdsense.html)
 
 **概要 [#t316cdb3]
 
 XMLと言えばUnicode(UTF-8)な訳だが、
 データによってはそうでないものも良くある。
 特に、日本語ってやつは面倒くさいことが多い。
 日本語の文字コードで代表的なものは、
 Shift-JIS, EUC-JP, UTF-8, ISO-2202-JP
 一つの言語でこれだけコードがあるのは日本語・中国語・韓国語ぐらいだろう。
 
 simple_xml関数を使用すると、
 UTF-8以外の文字コードを使用した場合、
 パーサエラーが出ることがある。
 結構きまぐれなのか、
 環境によって出たりでなかったりしているような印象だ。
 
 **multibyte関数との関係 [#r30cba2c]
 マルチバイトと言えばマルチバイト関数mb_convert_encodingが思いつくが、
 メインでは使用しない。
 Do you PHP?
 http://www.doyouphp.jp/php5/php5_simplexml.shtml
 では、
  マルチバイト文字を扱う場合、internal_encodingに変換して出力する
 と書いてあるが、
 これは正しくないと思われる。
 実際はSimpleXML、もっと言うならLibxml2とmb_convert_encodingは、
 なんの横つながりもない。
 
 **実際 [#u22a5a53]
 では実際どうなのかというと、
 Hawk's W3 Laboratory : XMLパーサ関数で日本語を扱う
 http://www.hawk.34sp.com/stdpls/php/xml_parse.html
 での記述。
  内部エンコーディングはUTF-8
  デフォルトでサポートしているエンコーディングは、
   UTF-8, UTF-16LE/BE, iso-8859-1, ASCII, HTML(エンティティ参照)
  iconv が利用可能な環境なら iconvがサポートしているエンコーディングが全て使える
 つまり、iconvが影響しているのだ。
 
 iconv(i18n converter)とは、
 文字コードの変換をする関数。
 iconvはlibiconvを使用した関数。
 マルチバイト関数はPHP独自実装。
 PHP 3.0.x国際化対応版、PHP4.2.2国際化版をPHPに取り込んだもの。
 やっていることはどちらも同じで、
 文字コードの変換を行っている。
 
 
 
 XMLのヘッダー部分に
  <?xml version="1.0" encoding="EUC-JP" ?>
 と記述してあるわけだが、
 このencode属性を読みとって、
 SimpleXMLは変換を行っている。
 デフォルトでは
  ISO-8859-1
  UTF-8 
  US-ASCII
 の3つにしか対応していないので、
 どんなに頑張っても文字化けする。
 UTF-8に変換すればいいと思う人もいるかもしれないが、
 その場合UTF-8に変換後、ヘッダー部分を
  <?xml version="1.0" encoding="UTF-8" ?>
 と書き換えなければならないので、
 少し面倒だ。
 
 そこで、iconvライブラリを使用すると、
 ほぼすべての言語に対応できるというわけ。
 
 **対処法 [#x4bac058]
 日本語を使用するときは、
 特別ソースコードを変更することはない。
 phpinfoに
  iconv
 があればよい。
 無い場合はのconfigureオプションに
  --with-iconv
 を追加しておく。
 
 
 fladdict.net blog
 rssに非UTF8の不正な文字列がある場合の対処法
 http://fladdict.net/blog/2006/06/rssutf8.html
 で、
  PHP5のSimpleXMLが、rss内に不正な文字列があるとパースエラーを起こしてしまうのだけど、
  ついに対処法を編み出した。
  というか朝思いつきでやったら動いたwwwww
  $xmlStr = mb_convert_encoding($xmlStr, "SJIS", "UTF-8");	//一度sjisにする
  $xmlStr = mb_convert_encoding($xmlStr, "UTF-8", "SJIS");	//またutf8に戻す
  mb_convert_encodingスゴス。
 とあるが、
 これはもう一つ進んだ話。
 条件は例えばこう
  ・XMLヘッダーに
   <?xml version="1.0" encoding="UTF-8" ?>
   と記述してある
  ・属性、値の中に別の文字コード(EUC-JP, SJISなど)が入っている
 と言った具合。
 つまり一度すべての文字コードを統一してから、
 SimpleXMLにパースさせると安全に文字変換が行える。
 
 **サンプル [#dbc07c4c]
 UTF-8,EUC-JP,SJISのXMLファイルを読み込むことを想定して、
 ソースはこんな感じだろうか。
  mb_detect_order("SJIS-win,EUCJP-win,UTF-8,JIS,ASCII");
  // get xml
  if( ! $xmlStr = file_get_contents( "http://hoge.com/hoge.xml" ) )
   throw new Exception("Not Open Url");
  // parse xml
  $encode = mb_detect_encoding( strip_tags( $xmlStr ) );
  $xmlStr = mb_convert_encoding( $xmlStr, $encode, mb_detect_order() );
  $xmlObjs = @simplexml_load_string( $xmlStr, "SimpleXMLIterator" );
  print_r( $xmlObjs );
 1行目を読みとって、
 encodingを取得する方がより安全かもしれない。
 -カピバラ -- [[みる]] &new{2006-11-21 13:26:48 (火)};
 -文字コードを見るのはpreg_match( '/xml version="1.0" encoding="(.*)/i' , $xmlStr, $matches ) ってこと?それともHTTPのHEADの方が良いでしょうか_? -- [[takuya_1st]] &new{2007-03-23 16:56:20 (金)};
 -HTTPのヘッダーはあまり参考にならないので、解析する形の方が良いと思います。・・・それにしても、自分で書いた文章ながら支離滅裂な内容に唖然としてしまった。(_ _ )/ハンセイ -- [[dozo]] &new{2007-03-23 20:16:53 (金)};
 
 #comment


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Third Project
証券会社ランキング比較