- 追加された行はこの色です。
- 削除された行はこの色です。
#freeze
#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, "SJIS-win,EUCJP-win,UTF-8,JIS,ASCII" );
$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