ようこそゲスト さん ユーザー登録 ログイン

php5でsimpleXMLを使っているのですが、名前空間の接頭辞のついた属性を取得する方法がわかりません。

<document>
<note ns:data="foo"></note>
</document>

こんな感じのイメージで"foo"を取得して配列に落とし込みたいのです。どなたかお知恵をいただけませんでしょうか。 php5でsimpleXMLを使っているのですが、名前空間の接頭辞のついた属性を取得する方法がわかりません。 <document> <note ns:data="foo"></note> </document> こんな感じの.. を含むブックマークはてなブックマーク - php5でsimpleXMLを使っているのですが、名前空間の接頭辞のついた属性を取得する方法がわかりません。 <document> <note ns:data="foo"></note> </document> こんな感じの.. - 人力検索はてな

  • hiroshimo あなたも質問に答えられます! ウォッチリストに追加
  • 状態:終了 いるか
  • 回答数:3 / 45件
  • 回答ポイント:80ポイント
  • 登録:2008-02-12 19:51:46
  • 終了:2008-02-13 17:45:37
  • カテゴリー:ウェブ制作ウェブ制作

3 回答者:tezcello 2008-02-13 13:49:02 満足! 26ポイント

フローを示すだけではアレなんで...

$str = <<< EOL
<?xml version="1.0" encoding="UTF-8"?>
<docs xmlns:ns="http://hoge/fuga/">
<document>
<note ns:data="foo">abcde</note>
</document>
<document>
<note ns:data="hoo">edcba</note>
</document>
<document>
<note data="poo">123</note>
</document>
<document>
<note ns:data="boo">abcde</note>
</document>
</docs>
EOL;

$prefix = ''; $ns = '';

// 接頭辞や名前空間が既知なら上で定義すれば下3行は不要
if (preg_match('/xmlns:([-\w.]+)="(.+?)"/', $str, $tmp)){
  $prefix = $tmp[1]; $ns = $tmp[2];
}

preg_match_all('/\s'.$prefix.':([-\w.]+)="(.*?)"/', $str, $tmp);

var_dump($tmp[2]);

// simplexml での処理が必要ならこの先も
//$xml = simplexml_load_string($str);
//$xml->registerXPathNamespace('namespace', $ns);
//$res = $xml->xpath('//note[@namespace:data="foo"]');
//var_dump($res);
// 次の行が得られる
// array(1) { [0]=>  object(SimpleXMLElement)#2 (1) { [0]=>  string(5) "abcde" } }

array(3) { [0]=> string(3) "foo" [1]=> string(3) "hoo" [2]=> string(3) "boo" }

http://jp.php.net/manual/ja/function.preg-match-all.php

質問者:hiroshimo 2008-02-13 14:40:31

回答ありがとうございます。非常にためになりました。少し質問のしかたがまずかったように思うので再度提示させていただきたいと思います。

<document>

<note data="foo">A</note>

<note data="bar">B</note>

</document>

うえのようなXMLがあったとして、AとかBを取り出そうとしたらこうですよね?

foreach ($xml as $document) {

echo $document->note, '
';

}

fooとかbarを取り出そうとしたら、こうですよね。

foreach ($xml as $document) {

echo $document->note[data], '
';

}

これをしたいのですが、dataにns:という接頭辞が付いているとうまくいきません。

foreach ($xml as $document) {

echo $document->note[ns:data], '
';

}

というようなことを解決したいのですが・・・。どうしたらいいのでしょう?

1 回答者:hatettyo 2008-02-12 22:18:49 満足! 27ポイント

$sample = array();
$data = @simplexml_load_file(XMLのURL);
$sample[] = $data->document->note;

こうゆう事でしょうか。

documentが複数ある場合は

$sample = array();
$data = @simplexml_load_file(XMLのURL);
foreach($data->document as $value){
    $sample[] = $value->note;
}

という感じですかね。

http://q.hatena.ne.jp/1201158240

2 回答者:tezcello 2008-02-13 11:17:34 満足! 27ポイント

名前空間が指定されている属性値を指定して取出したいという事でしょうか?

$str = <<< EOL
<?xml version="1.0" encoding="UTF-8"?>
<docs xmlns:ns="http://hoge/fuga/">
<document>
<note ns:data="foo">abcde</note>
</document>
<document>
<note ns:data="foo">edcba</note>
</document>
<document>
<note data="foo">123</note>
</document>
<document>
<note ns:data="boo">abcde</note>
</document>
</docs>
EOL;

$xml = simplexml_load_string($str);

$xml->registerXPathNamespace('namespace', 'http://hoge/fuga/');
var_dump($xml->xpath('//note[@namespace:]'));print "<br>\n";

$res = $xml->xpath('//note[@namespace:data="foo"]');
var_dump($res);

結果は、

array(2) {

[0]=>

object(SimpleXMLElement)#2 (1) {

[0]=>

string(5) "abcde"

}

[1]=>

object(SimpleXMLElement)#3 (1) {

[0]=>

string(5) "edcba"

}

}

そうじゃなくて、どんな属性が使われているかなら、

一旦 file_get_contents などで読み込み、

名前空間の接頭辞(xmlns をキーにして探す)を preg_match() 等で見つけて、

その接頭辞のついている属性を preg_match_all で探して配列に入れる

という手順が考えられます。

http://jp.php.net/manual/ja/function.simplexml-element-registerX...

おとなり質問

この質問・回答へのコメント

回答制限をしていたためtezcelloさんからの回答が掲載できませんでしたので、ここの再掲させていただきます。
====
回答数制限&コメントが付けられない なのでこちらか失礼します。

$str = <<< EOL
<?xml version="1.0" encoding="UTF-8"?>
<docs xmlns:ns="http://hoge/fuga/">
<document>
<note ns:data="foo">abcde</note>
</document>
<document>
<note ns:data="hoo">edcba</note>
</document>
<document>
<note data="poo">123</note>
</document>
<document>
<note ns:data="boo">ghijk</note>
</document>
</docs>
EOL;

$prefix = 'ns';

$xml = simplexml_load_string($str);

foreach ($xml as $x){
print 'attribute = '.$x->note->attributes($prefix, 1)."\n";
print 'children = '.$x->children()."\n";
print "\n";
}

こんな感じで、ご希望のものに近付いたのではないかと思うのですが、いかがでしょうか?

simplexml を熟知している訳ではないので、マニュアルを読み返してみて見つけました。
これを知っていれば、回答として示したものは、もっとスッキリしたものだったのに...
僕自身も大変勉強になりました。
====

tezcelloさん、ありがとうございました!

attributes属性にprefixを指定できるとは知りませんでした。すっきり解決しました。
ただ、間借りしているサーバーだと SimpleXMLElement::attributes() expects at most 1 parameter, 2 given というエラーが出るんですよね。調べたらphpが5.0.4でした。5.2.5 だと問題なかったんですが。

今回は大変勉強になりました。ありがとうございました。
いるか ありがとうございました。

5.1.x -> 5.2.x の際に、is_prefix が追加になったという記事が見つかりました。
という事は、接頭辞ではなく名前空間を指示すればよいのでは?
$x->note->attributes('http://hoge/fuga/', 1)
って感じで。

この質問・回答へのトラックバックこの質問・回答へのトラックバック

スパイスラボ神部です。 PHP5 には SimpleXML という大変便利な関数があるのですが、使いこなしにはいろいろコツがあるようです。 名前空間付の XML...
PHP5 の SimpleXML を使って処理するときのあれこれ ( ラボブログ ) http://blog.spicebox.jp/labs/2009/08/php5_simplexml.html PHP5 には SimpleXML という大変便利な関数があるのですが、使いこなしにはいろいろコ