xpath の記述方法について教えてください。


次のような xml ファイル (test.xml) があるとします。
<?xml version="1.0" encoding="UTF-8" ?>
<addressbook>
<address>1-2-3 <font color='#FF0000'>Tokyo</font>, JAPAN</address>
<phone>123456</phone>
<name>Taro Yamada</name>
</addressbook>

次のような PHP スクリプトを実行します。
<?php
$xml = simplexml_load_file ("test.xml");
$xpath = "/addressbook/address";
$data = $xml->xpath($xpath);
echo ($data[0]);
?>

echo で表示されるのは「1-2-3 , JAPAN」となります。
これを、「1-2-3 <font color='#FF0000'>Tokyo</font>, JAPAN」と表示するには xpath をどのように変更するべきか教えてください。

つまり、取得したい要素の下にさらに別の要素がある場合 (私の場合は html タグ) それらを通常のテキストとして扱う方法が知りたいということです。

よろしくお願いします。
ちなみに、取得した値は最終的にデータベースに格納します。

Apache 2.2.11
PHP 5.3.0
MySQL 5.1.36

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

ベストアンサー

id:tobeoscontinue No.2

回答回数220ベストアンサー獲得回数59

ポイント100pt

取得したい要素をasXML()でもう一度、XMLに戻してみてはどうでしょう。

var_dump ($data[0]->asXML());
var_dump (str_replace(array('<address>','</address>'), NULL, $data[0]->asXML()));
var_dump (substr($data[0]->asXML(),9,-10));

ただXMLなのでaddressタグが付加されます。不必要なら正規表現などで取り除く必要があります。

addressタグが固定ならstr_replaceやsubstrで取り除くと多少エコかと。

id:Nigitama

ありがとうございます。

これで解決です。

上でも書きましたが、合計100万レコード以上あり、1レコードには15~20要素 (内容はすべて把握しています) が含まれています。html が含まれている可能性があるのはそのうちの 2 つなので、データベースに格納する前に asXML() 処理をして前後のタグをカットすれば完璧です。

便利な関数を教えていただきありがとうございます。

2010/01/29 17:43:27

その他の回答1件)

id:yoneto164 No.1

回答回数813ベストアンサー獲得回数94

ポイント20pt

XMLの属性値を取得することは出来るので、

「1-2-3 , JAPAN」と「<font color='#FF0000'>Tokyo</font>」を取得することは可能ですが、

<address>1-2-3 <font color='#FF0000'>Tokyo</font>, JAPAN</address>

の場合XMLとして構文が間違っていると思われるので、

「<font color='#FF0000'>Tokyo</font>」がどこに入っていたかを返す命令が無いようです。


例えばtest.xmlを、

<addressbook>

<address>1-2-3 &lt;font color='#FF0000'&gt;Tokyo&lt;/font&gt;, JAPAN</address>

<phone>123456</phone>

<name>Taro Yamada</name>

</addressbook>

とすることは出来ないのでしょうか?

id:Nigitama

ありがとうございます。

シンプルですが確実な方法ですね。

xml要素の種類は20もないので、それらを秀丸の前方不一致、後方不一致で排除すれば、< を &lt; に変えることは可能です。

レコード数は複数ファイルに別れていますが、合計で100万件以上で、1件のレコードには10~15個くらいのxml要素が含まれているという状況です。

定期的に発生する作業なので、(秀丸にマクロ登録したとしても) No2 の方の回答を応用して自動化した方がよさそうです。

回答いただきありがとうございました。Thank you anyway.

2010/01/29 17:36:23
id:tobeoscontinue No.2

回答回数220ベストアンサー獲得回数59ここでベストアンサー

ポイント100pt

取得したい要素をasXML()でもう一度、XMLに戻してみてはどうでしょう。

var_dump ($data[0]->asXML());
var_dump (str_replace(array('<address>','</address>'), NULL, $data[0]->asXML()));
var_dump (substr($data[0]->asXML(),9,-10));

ただXMLなのでaddressタグが付加されます。不必要なら正規表現などで取り除く必要があります。

addressタグが固定ならstr_replaceやsubstrで取り除くと多少エコかと。

id:Nigitama

ありがとうございます。

これで解決です。

上でも書きましたが、合計100万レコード以上あり、1レコードには15~20要素 (内容はすべて把握しています) が含まれています。html が含まれている可能性があるのはそのうちの 2 つなので、データベースに格納する前に asXML() 処理をして前後のタグをカットすれば完璧です。

便利な関数を教えていただきありがとうございます。

2010/01/29 17:43:27
  • id:kn1967
    最後までお付き合いできるかも判らないし、
    あまり回答熱意も無いのでヒントだけ、コメントに残します。

    まずは下記を実行してみてください。
    $xml = simplexml_load_file ("test.xml");
    $xpath = "/addressbook/address";
    print_r($xml->xpath($xpath));

    次に下記を実行してみてください。
    $xml = simplexml_load_file ("test.xml");
    $xpath = "/addressbook/address/*";
    print_r($xml->xpath($xpath));

    以上で、何が足りないのか、どのようになってるのかが判ると思いますので、
    あとは、必要に応じて各要素を取得、合成、出力という事になります。

    事にはなるのですが・・・
    xpathによる分解が「必ずしも目標達成への近道とは限らない」です。
    不要なタグを除きながら、先頭から1行ずつ順に読み込んでいって、
    必要な部分を吐き出すといったベタな方法も一度考えてみてください。

    それでは、失礼。

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

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

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

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