「PHPでXPath を使用する」を勉強しています。
https://www.ibm.com/developerworks/jp/xml/library/x-xpathphp/
上記サイトのproducts.xmlを対象に、
「リスト 2. SimpleXML を使用し、すべてのノードを配列として表示する」
はそのままできるのですが、
「リスト 3. SimpleXML を使用し、すべての製品名を配列として表示する」
<?php
$xml = simplexml_load_file("products.xml");
$products = $xml->xpath("/PRODUCTS/PRODUCT/NAME");
print_r($products);
?>
*$products = $xml->xpath("/PRODUCTS/PRODUCT/NAME");
の部分が違うだけです。
だと、配列に何もはいりません。
Array ( [0] => SimpleXMLElement Object ( )
*この状態が、[0]~[3]まで表示
何が悪いのかわかりません。
教えていただけると大変助かります。
よろしくお願いします。
ありがとうございます。
コメントをまとめただけの回答で失礼します。
PHPのバージョン5.6.11、および5.5.27で修正されたようです。
最新版の5.6.14では正常に取得できる事を確認済みです。(※5.6.11および5.5系最新の5.5.30でも確認済みですが、5.5.27は未確認)
・PHP 5 ChangeLog
http://php.net/ChangeLog-5.php#5.6.11
Version 5.6.11
10 Jul 2015
- SimpleXML:
- Refactored the fix for bug #66084 (simplexml_load_string() mangles empty node name).
・Bug #66084 simplexml_load_string() mangles empty node name
https://bugs.php.net/bug.php?id=66084
・Fix #66084: whitespace depending iteration over SimpleXMLElements (php-src/1306)
https://github.com/php/php-src/pull/1306
英語が苦手なので全部は読んでいませんが、「var_dump」や「print_r」だけでなく「json_encode」にも影響があるという事です。
※libxmlの問題ではありませんでした。修正前の5.6.10でもバージョン2.9.2です。
単純にIBMのページの内容が正しくない(あるいは今のバージョンとは応答が違う)のだろうと思います。
__ミスもあるようですしね
__[SKU='soft5678'] で Pro Reporting が得られるみたいな記述だけど
__「Pro Reporting」は SKUが soft32323 だし(というか soft5678 は存在しない)
> Array ( [0] => SimpleXMLElement Object ( )
良く考えてみれば、これで良いんじゃないでしょうか?
xpath() の戻り値 $products は単なる配列で $products[0] は SimpleXMLElement。
$products[0] は何らかのプロパティやノードを含んでいる訳ではないので $product[0] は SimpleXMLElement としか表示できない。
例えば、
<NAME><AAA>hoge</AAA>Widget Reporting</NAME>
のように書いてやれば
Array ( [0] => SimpleXMLElement Object ( [hoge] => fuga )
のようになります。
「products.xml」の中身は同じなのでしょうか?(※「リスト 1. 製品群を表現する XML 文書の例 (products.xml)」をコピー)
products.xmlの中身は
<?xml version="1.0" encoding="UTF-8"?>
<PRODUCTS>
<PRODUCT category="software">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Business Analysis</SUB_CATEGORY>
<NAME>Widget Reporting</NAME>
<PRICE>4500</PRICE>
</PRODUCT>
<PRODUCT category="software">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Business Analysis</SUB_CATEGORY>
<NAME>Pro Reporting</NAME>
<PRICE>2300</PRICE>
</PRODUCT>
<PRODUCT category="storage">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Tape Systems</SUB_CATEGORY>
<NAME>Tapes Abound</NAME>
<PRICE>2300</PRICE>
</PRODUCT>
<PRODUCT category="storage">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Disk Systems</SUB_CATEGORY>
<NAME>Widget100 Series</NAME>
<PRICE>6500</PRICE>
</PRODUCT>
</PRODUCTS>
$products = $xml->xpath("/PRODUCTS/PRODUCT");
だと、配列にしっかり値が入っています。
いつも、お手数おかけしてすいません。
それから、PHPやlibxmlのバージョンはいくつでしょう?(「phpinfo()」で確認してみてください。)
・指定方法を変えた場合はどうなりますか?
$products = $xml->xpath("//NAME");
・「NAME」ノード以外で同じ階層にあるノードの取得結果も確認してみてください。
$products = $xml->xpath("/PRODUCTS/PRODUCT/SUB_CATEGORY");
あるいは
$products = $xml->xpath("/PRODUCTS/PRODUCT/PRICE");
OSやウェブサーバーの種類等、テスト環境
->
Windows8.0
Apache2.4
php5.6.2
libxml:2.9.1
$products = $xml->xpath("//NAME");
->配列に何も入ってないです。
$products = $xml->xpath("/PRODUCTS/PRODUCT/SUB_CATEGORY");
->やはり、配列に何も入ってないです。
$products = $xml->xpath("/PRODUCTS/PRODUCT/PRICE");
->やはり、配列に何も入ってないです。
お手数おかけして、すいません。
Windows版で問題の現象が発生するのを確認できました。(※Linux版では未確認ですので、Windows版だけの問題の可能性もあります。)
最新版のPHP 5.6.14(libxml 2.9.2)では正常に取得できましたので、PHPを最新版にアップグレードしてみてください。
何かエラーメッセージは出ていますか?
Apache、PHP、MySQLをそれぞれ別々にインストールしたのでしょうか?
それともXamppでしょうか?
別のパソコンに新規にapche2.4.16と
http://php.net/ から VC11 x86 Thread Safe (2015-Oct-01 01:19:35)
をダウンロードして、php5.6.14インストールしています。
(それとMySQL)
php.ini(c:\phpに配置)、apacheのconf(c:\Tools\htdocs\confに配置)
でphp.iniとhttpd.confファイルは見直したつもりなのですが。
現象:info.php(<?php phpinfo(); ?>)で、このまま文字列で<?php phpinfo(); ?>が表示されます。
通常使っているパソコンではできているので、あれこれやっているところです。
何から何まですいません。
そちらのPCと今回新たにインストールしているPCでは、各環境を別の方法でインストールしているのですか?
Apacheのインストール先の確認です。
> apacheのconf(c:\Tools\htdocs\confに配置)
Apacheの設定ファイル「httpd.conf」を「c:\Tools\htdocs\conf」に入れてあるのでしょうか?
Apache本体は何処にありますか?
「htdocs」はドキュメントルート用に用意されたディレクトリです。
通常は「htdocs」と同じ階層に「conf」ディレクトリがあります。
Apacheの場合、各種ファイルの場所は変更せず、階層を維持したままインストールする方が良いと思います。(※特にWindowsでのテスト環境では必要ないと思います。)
他、とりあえずPHPに関する設定について、次の2点について確認してみてください。
1.PHPのApache用モジュールを読み込む設定を追加していますか?
以下を「httpd.conf」に追加します。(各種ディレクティブの外側なら何処でも大丈夫です。)
(※「C:/php/」がPHPのディレクトリの場合の例)
LoadFile "C:/php/php5ts.dll"
LoadModule php5_module C:/php/php5apache2_4.dll
PHPIniDir C:/php/
・Apache モジュール mod_so #LoadModule ディレクティブ
http://httpd.apache.org/docs/2.4/mod/mod_so.html#loadmodule
※コンテキストが「サーバ設定ファイル」と「バーチャルホスト」です。
・ディレクティブの解説に使われる用語 #コンテキスト
http://httpd.apache.org/docs/2.4/mod/directive-dict.html#Context
2.PHPファイルをPHPとして動作させる為の設定を追加していますか?
「<Directory>」ディレクティブ内でも設定できますので、「httpd.conf」のドキュメントルートディレクトリの設定内に記述してみてください。
# ドキュメントルートのディレクトリは設定例です。
DocumentRoot "C:/example/www"
<Directory "C:/example/www">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
# ...(~略~)
Options Indexes FollowSymLinks
# ...(~略~)
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
</Directory>
※「.phps」ファイルをPHPのソースファイルとして表示させる場合は以下も追加
<FilesMatch "\.phps$">
SetHandler application/x-httpd-php-source
</FilesMatch>
・PHPに関するApacheの設定
http://www.adminweb.jp/xampp/php/index3.html
※各種設定ファイルの設定変更後はApacheの再起動が必要です。
に記載のある
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
の2行をconfに追加したらできました。
お手数おかけしてすいません。
できました。
->
この質問の
$products = $xml->xpath("/PRODUCTS/PRODUCT/NAME");
も表示されました。
ありがとうございました。
rouge_2008 さんを
ベストアンサーにさせていただきたいのですが、
正式なご回答いただけませんか。
よろしくお願いします。
foreach ($products as $p) print_r($p->__toString());
や
foreach ($products as $p) echo $p;
でテキストが表示されました。
「SimpleXMLElement::__toString()」や「echo」以外でも文字列として認識させると大丈夫なようです。(「print」「printf()」等)
型を変換したり、明示的にセットする事でも表示されました。
・型の相互変換
http://php.net/manual/ja/language.types.type-juggling.php
・settype
http://php.net/manual/ja/function.settype.php
値を直接「var_dump()」で確認すると次のようになっています。
------------------------------------
foreach($products as $p) {
var_dump($p);
}
結果:
object(SimpleXMLElement)#8 (0) {
}
object(SimpleXMLElement)#9 (0) {
}
object(SimpleXMLElement)#2 (0) {
}
object(SimpleXMLElement)#3 (0) {
}
------------------------------------
※オブジェクトのカウントが0です。
バージョン5.6.11と5.5.27で修正されたようです。
英語が苦手なので全部は読んでいませんが、「var_dump」や「print_r」だけでなく「json_encode」にも影響があるようでした。
・PHP 5 ChangeLog
http://php.net/ChangeLog-5.php#5.6.11
・Bug #66084 simplexml_load_string() mangles empty node name
https://bugs.php.net/bug.php?id=66084
・Fix #66084: whitespace depending iteration over SimpleXMLElements (php-src/1306)
https://github.com/php/php-src/pull/1306
※libxmlの問題ではありませんでした。修正前の5.6.10でもバージョン2.9.2です。
コメントをまとめて回答しました。
無事にバージョンアップ完了したという事で良かったです。
※誤字を修正して再投稿しています。