phpで以下のXMLデータを読み込む方法を教えてください。

XMLデータはsample.xmlという名称で保存していると仮定してます。

<?xml version="1.0" encoding="UTF-8"?>
<aaa age_limit="LL">
<rank point="0.40000" order="1"> <team area3="青葉区" area2="横浜市" area1="神奈川県" email="" url="" name="ZZZZ" id="123456"/>
</rank>
</aaa>
読み込みたい箇所は
age_limit
order
area3
area2
area1
id
です。
よろしくお願い致します。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2011/06/21 20:16:09
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:pacochi No.1

回答回数247ベストアンサー獲得回数113

ポイント100pt

SimpleXML を使う方法です。PHP5 では標準で使えるようになっていると思います。

<?php
$aaa = new SimpleXMLElement('./sample.xml', NULL, true);

$age_limit = $aaa['age_limit'];
$order = $aaa->rank['order'];
$team = $aaa->rank->team;
$area3 = $team['area3'];
$area2 = $team['area2'];
$area1 = $team['area1'];
$id = $team['id'];

# LL, 1, 青葉区, 横浜市, 神奈川県, 123456
echo "{$age_limit}, {$order}, {$area3}, {$area2}, {$area1}, {$id}";
exit;
?>

以下コメントを受けての追記です。(2011.6.21 20:00 修正しました。)


何故か XML のデータがどこかで Shift_JIS に変換されているようです。

ファイルを直に読み込むのではなく、一旦文字列として読み込んで、念のため UTF-8 に変換してからその文字列を与える形にしてみました。

また、複数の <rank> の値を取得するように変更しています。

<?php
# 下二行はエラー表示用なので表示に成功したら削っても構いません
ini_set('display_errors', 'On');
error_reporting(E_ALL);

$xml_str = file_get_contents('./sample.xml');
# 文字コードを UTF-8 に
$xml_str = mb_convert_encoding($xml_str, 'UTF-8', 'auto');

$aaa = new SimpleXMLElement($xml_str);

$age_limit = $aaa['age_limit'];
echo "{$age_limit}\n";

# <rank> ごとの内容を表示
foreach ($aaa->rank as $rank) {

	$order = $rank['order'];
	$area3 = $rank->team['area3'];
	$area2 = $rank->team['area2'];
	$area1 = $rank->team['area1'];
	$id = $rank->team['id'];

	echo "{$order}, {$area3}, {$area2}, {$area1}, {$id}\n";

}

# id だけ取ってきて配列に格納
# order なら '/aaa/rank/@order' になります
# area3 なら '/aaa/rank/team/@area3' になります
$id_list = $aaa->xpath('/aaa/rank/team/@id');
# 配列の内容を表示
foreach ($id_list as $id) {

	echo "{$id}, ";

}

exit;
?>

もし、これでも駄目でしたら、ちょっと大仰になってしまいますが DOMDocument を使うという方法もあります。(こちらも文字コードを変換して読み込むよう修正しました。)

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);

$xml_str = file_get_contents('./sample.xml');
$xml_str = mb_convert_encoding($xml_str, 'UTF-8', 'auto');

$doc = new DOMDocument('1.0', 'UTF-8');
$doc->loadXML($xml_str, LIBXML_NOBLANKS);
$xpath = new DOMXpath($doc);

$age_limit = $xpath->query('/aaa/@age_limit');
echo $age_limit->item(0)->nodeValue . "\n";

$rank_items = $xpath->query('/aaa/rank');

foreach ($rank_items as $rank) {

	$order = $rank->getAttribute('order');
	$area3 = $rank->firstChild->getAttribute('area3');
	$area2 = $rank->firstChild->getAttribute('area2');
	$area1 = $rank->firstChild->getAttribute('area1');
	$id = $rank->firstChild->getAttribute('id');

	echo "{$order}, {$area3}, {$area2}, {$area1}, {$id}\n";

}

exit;
?>

ただ、SimpleXML も DOMDocument も処理する本体の部分は同じ (libxml 拡張モジュール) なので、その本体の部分でエラーが出ている場合はあまり意味は無いかもしれません。

id:vfr6822

ありがとうございます頂いた情報ではうまく表示できませんでした。

php5です。

<rank point~>////</rank>までが複数あったので

xml内のデータを変えてみても表示できません。

何が悪いのでしょうか??

2011/06/21 13:42:18
  • id:pacochi
    私の書いたサンプルでは、<rank> が複数あった場合には一番最初の <rank> の内容を表示するはずですが、それすら表示されていないという事でしょうか。
    もしエラーなどが出る場合は、エラーの文面なども教えて下さい。
  • id:vfr6822
    エラーの文面はまったくでません。対象となる箇所が真っ白になってます。
    お手数おかけします。。。
  • id:pacochi
    すみません、今のところ何故表示できないのか原因を特定できていません。

    私が使用した XML ファイル (内容は質問文の XML) です。
    http://d.hatena.ne.jp/pacochi+tb/files/sample.xml?d=download
    お手数ですが、上記の XML ファイルでもうまく表示されない (「, , , , ,」のような表示になる) かどうか、ご確認下さい。

    また、
    <?php
    $aaa = new SimpleXMLElement('./sample.xml', NULL, true);
    echo $aaa->asXML();
    ?>
    とした場合、XML データが出力されているかどうかも、よろしければご報告下さい。
    (ブラウザで結果を表示している場合はソースを表示して確認して下さい。)
  • id:vfr6822
    頂いたxmlとソースで試したら同様に画面が真っ白でした。
    真っ白の画面ソースは

    ---------------------------
    <html>
    <title>タイトル</title>
    </head>
    <body>
    ---------------------------
    で終わってまして、</body></html>が表示されてませんでした。
    phpの終わり方が間違えているのでしょうか?



  • id:pacochi
    取得しようとした文字だけではなく、コンマも何も表示されていなかったのですか。

    <?php
    error_reporting(E_ALL);
    header('Content-type: text/html; charset=UTF-8');
    echo "start<br>\n";

    $aaa = new SimpleXMLElement('./sample.xml', NULL, true);
    echo "aaa = \n";
    echo htmlspecialchars($aaa->asXML());

    echo "<br>\nend<br>\n";
    exit;
    ?>

    何度もすみません、上記のスクリプトでどのような表示になるか試していただけませんか。
  • id:vfr6822
    こちらこそ何度もすみません。
    頂いたソースで試したら

    start

    のみ表示されました。。。。
  • id:pacochi
    SimpleXML を使おうとしたところで多分エラーが出ているのだとは思うのですが、エラーの内容が分からないので手探りになってしまいます。
    エラーの出ない原因が SimpleXML を使おうとしたことにあるのか、それとも他に原因があるのかも分からないです。
    普段エラーを表示するような設定にはしているのでしょうか。

    <?php

    echo 'display_errors=' . ini_get('display_errors')
    . ', html_errors=' . ini_get('html_errors')
    . ', error_reporting=' . ini_get('error_reporting') . "<br>\n";

    ini_set('display_errors', 'On');
    ini_set('html_errors', 'On');
    error_reporting(E_ALL);

    $SimpleXML_exists = (class_exists('SimpleXMLElement')) ? 'exists' : 'not exists';
    echo "SimpleXML {$SimpleXML_exists}.<br>\n";

    $aaa = new SimpleXMLElement('<' . '?xml version="1.0" encoding="UTF-8"?' . '> <aaa age_limit="LL" />');
    echo htmlspecialchars($aaa->asXML());

    ?>

    小出しにしてすみません。上記のスクリプトで表示された結果を教えて下さい。
  • id:vfr6822
    下記のようなメッセージが出ております。

    display_errors=, html_errors=1, error_reporting=4177
    SimpleXML exists.
    <?xml version="1.0" encoding="UTF-8"?> <aaa age_limit="LL"/>

    お手数ですが、よろしくお願い致します。


  • id:pacochi
    回答に追記しました。
    以降しばらく (夜か明日の朝くらいまで) 返信できないかもしれません。
  • id:vfr6822
    頂いたスクリプトで
    複数のrankの値に対応したものは
    Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Input is not proper UTF-8, indicate encoding ! Bytes: 0x90 0xC2 0x97 0x74 in 省略.php on line 15

    Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <rank point="0.40000" order="1"> <team area3="�—t��" area2="���l�s" area1="�_�� in 省略.php on line 15

    Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in 省略.php on line 15

    Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in 省略.php :15 Stack trace: #0 省略.php (15): SimpleXMLElement->__construct('<?xml version="...') #1 {main} thrown in省略.php on line 15


    また、DOMでは
    Warning: DOMDocument::load() [domdocument.load]: Input is not proper UTF-8, indicate encoding ! Bytes: 0x90 0xC2 0x97 0x74 in (省略)sample.xml, line: 3 in 省略.php on line 14

    Notice: Trying to get property of non-object (省略).php on line 18

    とエラーメッセージが出てしまいました。
    お忙しい中すみません。またお時間がありましたらお願いします。

  • id:pacochi
    エラー内容のご報告ありがとうございます。回答を修正しました。

    いただいたエラーの内容を見ると、どうも XML の文字エンコーディングが Shift_JIS になってしまっているみたいです。
    保存した XML ファイルが何かの拍子に Shift_JIS になってしまったのか、それともファイルを読み込んだタイミングで勝手に変換されているのか分かりませんが、とりあえず PHP 側で UTF-8 に変換し直すよう、回答中の二番目と三番目のスクリプトを修正しました。
    ひとまず現在と同じエラーは出なくなると思います。
  • id:vfr6822
    何度もすみませんでした。
    おかげさまで表示できました!!
    -------------------------------------------------
    LL 1, 青葉区, 横浜市, 神奈川県, 123456 123456,
    -------------------------------------------------

    何度もご回答いただいてありがとうございました!
  • id:pacochi
    表示できたようで良かったです。エラー特定に辛抱強くお付き合いいただきありがとうございました。

    もしファイルの内容自体が Shift_JIS になっていた場合は、できればそちらをエディタなどで開いて UTF-8 として保存し直しておいて下さい。
    そうしたら「$xml_str = mb_convert_encoding($xml_str, 'UTF-8', 'auto');」という行は不要になりますので、削除するかコメントアウトしておいて下さい。
    (残しておいても動作に支障はありませんが、無意味な処理になります。)

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません