PHPでXMLのタグの有無を判定する方法

このQ&Aのポイント
  • PHPを使用してXMLのタグの有無を判定する方法について説明します。XMLファイル中に特定のタグが存在するかどうかを判定することで、エラーを回避することができます。
  • 具体的には、getElementsByTagName関数を使用して特定のタグの要素を取得し、その要素が存在するかどうかを判定します。isset関数を使用することで、要素が存在するかどうかを確認できます。
  • タグが存在しない場合には、取得した要素は空であるため、isset関数での判定結果はfalseとなります。このため、isset関数を使用した条件分岐を行うことで、タグの有無を判定することができます。
回答を見る
  • ベストアンサー

XMLのタグの有無をPHPで判定したい。

example1.xml ----------------------- <item>  <color>red</color>  <omake>candy</omake> </item> ----------------------- example2.xml ----------------------- <item>  <color>black</color> </item> ----------------------- 上記はXMLファイルの2パターンを示したものです。 商品(item)によって、オマケ(omake)があったりなかったりします。 オマケがない時には、タグ自体存在しません。 なので、タグがない時に、そのデータをDOMで取得しようとすると、 エラーが吐かれます。 Notice: Trying to get property of non-object in~~~ 私がしたいことは、 タグがない場合には、値を取得しない。 という分岐をさせることです。 例えば、 $items = $doc->getElementsByTagName('color'); if(isset($items)){echo $items->item(0)->nodeValue;} こんな感じで考えたのですが、ダメでした。 タグが無くても、$itemsはNULLではないため、 if文の中に入ってしまい、 結局、$items->item(0)->nodeValue; を通過しようとして、 Notice: Trying to get property of non-object in~~~ が吐かれます。 ($itemsは、object(DOMNodeList)#3 (0) { }といった内容で、NULLではない。) また、 if(isset($items->item(0)->nodeValue)){  echo $items->item(0)->nodeValue; } のようにすると、 isset()のところで、やはり、 $items->item(0)->nodeValue を通過しようとして、 Notice: Trying to get property of non-object in~~~ が吐かれます。 こういった場合、どうしたら良いのでしょうか。 宜しくお願いします。 (PHP5の環境です。)

  • PHP
  • 回答数3
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

getElementsByTagNameはNULLを返しません。必ず、DOMNodeListを返します。 そしてDOMNodeListは、lengthというプロパティを持ちます。 ので、 <?php $omake = $doc->getElementsByTagName('omake'); echo $omake->length; //存在しないなら『0』を返します。 ?> といった感じです。

LC-32SC1
質問者

お礼

どうもありがとうございます。 なるほど、そうやって判定をするんですね。 解説、とてもよく分かりました。 ありがとうございます。 問題解決です! ちなみに、以下のような判定方法では、 ダメでしょうか? 何か、抜け はありますか? $items = $doc->getElementsByTagName('omake'); if($items->item(0) !== NULL){  echo 'omakeタグはあります!'; }

その他の回答 (2)

回答No.3

その方法でも出来るのであれば問題ないのでしょうけど、メソッドを叩くだけ、オーバーヘッドになるので、 プロパティで値が引けるのであれば、プロパティで値を確認したほうが良いと思います。 そして、正しく引く方法が提供されているのに使わない、というのは筋が悪い、と私は思います。 ちなみに、限定してXMLを操作するなら、 http://jp2.php.net/manual/ja/book.simplexml.php こちらもありますので、何か使い勝手の面で思うところがあったら、試してみても良いかもしれません。

LC-32SC1
質問者

お礼

どうもありがとうございます。 とても勉強になりました。 教えて頂いた方法で判定するように致します。 私が書いたもう1つの方法は、 今回教えて頂くまでの間にvar_dump()を使って試行錯誤した結果、 偶然、見つけた方法だったので、 良いか悪いかよく分からずに使っておりました。 ちゃんとした方法があるのであれば、 そちらを使えるようになりたいので、 教えて頂き、とても助かりました。

noname#243182
noname#243182
回答No.1

XPath を使って要素の有無を確認してはいかがでしょうか。

参考URL:
http://jp.php.net/manual/ja/class.domxpath.php
LC-32SC1
質問者

お礼

どうもありがとうございます。 結論から先に言うと、解決しましたが、 できなかった原因は、XPathでやらなかったことにあるのではなく、 isset()で判定したことにありました。 if($hoge !== NULL){~~~;} として判定すると上手くいきました。 if(isset($hoge)){~~~;} ではダメなのです。 $hoge が NULLかどうかの判定には、どちらで判定しても、 結果は同じだと思っていたのですが、実際には、ハッキリと違いました。 なぜ違うのかについて、もしご存知の方は、是非教えて下さい。

関連するQ&A

  • PHP5でxml文書をパースする方法

    <?xml version="1.0"?> <root> <items>  <item>   <id>1</id>   <name>商品(赤)</name>   <price>1500</price>   <color>red</color>   <size>8</size>   <option>A</option>  </item>  <item>   <id>2</id>   <name>商品(青)</name>   <price>700</price>   <color>blue</color>   <size>3</size>  </item>  <item>   <id>3</id>   <name>商品(緑)</name>   <price>1200</price>   <color>green</color>   <size>5</size>   <option>C</option>  </item> </items> </root> 上記のようなXMLデータをPHPでパースし、 1つずつ、配列に入れていきたいと考えていますが、 問題なのは、 上から2番目の商品(青)には、<option>データが無いということです。 これは、この<option>が、オプションが有る時にだけ存在するタグだからです。 //----------------------------- <?php $doc->load($url); //上記xmlデータのあるURL:$url $array = array(); $i = 1; while($i <= 3){  //実際には、もっと商品数はあります。ここでは例として、3。  //配列の初期化  $item_array = array();  $items = $doc->getElementsByTagName('id');  $item_array['id'] = $items->item($i)->nodeValue;  $items = $doc->getElementsByTagName('name');  $item_array['name'] = $items->item($i)->nodeValue;  //*  //*同様のコードが続く  //*  $items = $doc->getElementsByTagName('option');  $item_array['option'] = $items->item($i)->nodeValue;  //*  //*同様のコードが続く  //*  //商品データが詰まった配列を、さらに配列に入れる  $array[] = $item_array; } //全ての商品のデータが詰まった配列を表示する。 print_r($array); ?> //----------------------------- このようなことがしたいわけです。 なお、タグ名を$tag_array = array('id','name',,,,,'option',,,)として、 foreach($tag_array as $tag){  $items = $doc->getElementsByTagName($tag);  $item_array[$tag] = $items->item($i)->nodeValue; } という風にした方が冗長ではないかとは思いますが、 それは、まぁ横に置いておきまして、 このコードで問題なのは、<option>が途中、つまり2番目で抜けると、 3番目の<option>データが、2番目の商品の<option>データとして配列に入ってしまうことです。 上から順に詰めて、配列に格納されてしまい、困っている、ということです。 <option>データが無い場合は、「ナシ」とでもしておきたいのですが、 どうしたら良いでしょうか? <item>を1つずつ   $items = $doc->getElementsByTagName('item'); で取得して、 各<item>の中の、<option>にアクセスする、なんて方法があるとベストなのですが、 そんな方法はありますでしょうか? firstChildですと、<item>の場合、<id>になってしまうため、<option>にはアクセスできません。 firstChild以降のChildには、どうやってアクセスしたら良いのでしょうね? どなたか、宜しくお願い致します。

    • ベストアンサー
    • PHP
  • XMLのURLをPHP表示したいのですが

    ご質問失礼いたします。 XMLをPHPで表示させたくて、下記のようにPHPファイルを作りました。 <?php $xmlfile = "xmlのURL"; $article=file_get_contents($xmlfile); echo "<table><tr><td>題名</td><td>リンク</td></tr>"; foreach($article->ItemLookupResponse->Items->Item as $data){ echo "<tr><td>"; echo $data[Title]; echo "</td><td>"; echo $data[ItemLinks->ItemLink asURL]; echo "</td></tr>"; } echo "</table>"; ?> echo $article;//で確認したXML(表示に必要な部分だけに省略させていただきました) <?xml version="1.0" ?> <ItemLookupResponse xmlns="http://www.~"> <Items> <Item> <Title>たいとる</Title> <ItemLinks> <ItemLink> <URL>http://www.~</URL> </ItemLink> </ItemLinks> </Item> </Items> </ItemLookupResponse> しかし、表示されず原因を特定することができません。 XMLだけを表示すると、 「This XML file does not appear to have any style information associated with it. The document tree is shown below.」 とは出ますが、情報はきちんと出ていると・・・思います。 PHPのファイルはページのソースを確認しても問題ないように見えたので、 表示の方法かXMLが違うのか、ご指摘いただければと思います。 すみません、知識が未熟な為、伝わりにくかったら申し訳ございませんが、 何卒お力をいただけたらと思います、宜しくお願い致します。

    • ベストアンサー
    • XML
  • 配列内のnodeValueがとれない

    XMLをAjax経由で受け取り、JavaScript内で処理をしたのいのですが、 XML要素にうまくアクセスできません。 具体的には、下記のXMLの、 <jcity></jcity>のタグを繰り返しでalert表示をさせたい (alert(r.childNodes[0].nodeValue))の部分で、、 何も表示されません。 原因などわかればご教授いただけますでしょうか。 よろしくお願いいたします。 ------以下、XML------------------------------- <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <items> <item> <jcity>千代田区</jcity> <jlocal>千代田</jlocal> <jpref>東京都</jpref> <pref_cd>13</pref_cd> <zip_cd>1000001</zip_cd> </item> </items> ------以下、JavaScript------------------------------- function rssFeed() { var myAjax = new Ajax.Request( 'http://myserver.co.jp/modules/api/rssfeed.class.php', { method: 'GET', onSuccess: showResponse, onFailure: errorFunc } ); } function showResponse(req) { r = req.responseXML; $A(r.getElementsByTagName('item')).each(function(r) { alert(r.childNodes[0].nodeValue); }); }

  • Excel-VBAでXMLの複数ノードの取り出し

    すみません、いつも、いろいろな方に助けて頂いていますが、また、初歩的な質問をさせて頂きます。 Excel2007のVBAでXMLの扱いが良くわかっておりません。 以下のプログラムで複数ItemのASINを出力したいのですが、うまくいきません。 XMLがきちんと取得できているのはWireSharkでキャプチャして確認できております。 VBAで表示出力するのがうまくいきません。ご教授方よろしくお願いします。 selectSingleNodeで一つの場合はうまく取り出せています。複数ノードの場合にSelectNodesの使い方に問題がありますでしょうか? 型の宣言などに誤りがありますでしょうか? また、基本的なことですが、MSXML2を使おうとしたら、Excel2007で使えませんでした。 XMLDOMは、サポート切れ?で古いので、MSXML2を使うのが良いとWebで見ました。 DLLなどが必要な気がしているのですが、よくわかっていないのでご教授頂きたいです。 すみませんが、よろしくお願いします。 *****VBAプログラム(抜粋)****** Dim xml As Object, xmlItems As Object, objPrice As Object 'XML オブジェクト作成 Set xml = CreateObject("Microsoft.XMLDOM") xml.async = False xml.Load URI Set xmlItems = xml.SelectNodes("ItemLookupResponse/Items/Item") For Each objPrice In xmlItems ' ASIN If Not objPrice.SelectSingleNode("ASIN") Is Nothing Then curWS.Cells(rowIndex, ASINCol) = objPrice.SelectSingleNode("ASIN").text End If Next *****取得したXML(抜粋)****** <ItemSearchResponse > <Items> <Item> <ASIN>111</ASIN> </Item> <Item> <ASIN>222</ASIN> </Item> <Item> <ASIN>333</ASIN> </Item> </Items> </ItemSearchResponse>

  • XML::DOM / XML::XPathでソート

    XML::DOMで効率的なソートの方法はどんなものがありますでしょうか。 一応動くものは作れたのですが、効率的とは言い難く、しかも ソート項目が一意のデータでないといけないという欠点があります。 ############################################### use XML::DOM::XPath; my $xml = <<EOM; <?xml version="1.0" encoding="UTF-8" ?> <list> <item id="10">Apple</item> <item id="5">Orange</item> <item id="20">Melon</item> </list> EOM my $parser = XML::DOM::Parser->new(); my $doc = $parser->parse( $xml ); ## <item>タグの一覧を作成 my @list = $doc->findnodes('/list/item'); ## <item>タグ id属性一覧を作成 my @idlist = map{ $_->getAttribute("id") } @list; ## id属性順にソート foreach my $id ( sort{ $a<=>$b } @idlist ){ ## id属性値を指定してノードリストを取得 my @item = $doc->findnodes('/list/item[@id='.$id.']'); ## idは一意なのでリストの先頭で固定 print $item[0]->getAttribute('id')."\n"; print $item[0]->getFirstChild->getNodeValue."\n"; } ############################################### ハッシュなら sort{ $hoe{$b} <=> $hoe{$a} } keys %hoe といった方法があるのですが、XML::DOMの場合は同じようにいきません。 良い方法がありましたらお願いします。

    • ベストアンサー
    • Perl
  • PHP4でXMLを取得する方法

    XMLをPHPにて参照したいのですが、 レンタルサーバーがPHP4の為、PearのXML_Unserializerを使用しています。 通常問題なく使用できていたのですが、 http://weather.livedoor.com/forecast/rss/index.xml から取得してみようとした所、<ldWeather:lwws id="*" /> の箇所がどうしても取得出来ません。 print_rにて確認したところ、[ldWeather:lwws]となっているのですが、コロンがある場合はどのように取得したらいいのでしょうか? 以下がコードになります require_once("Unserializer.php"); $add = "http://weather.livedoor.com/forecast/rss/index.xml"; $xmldoc = join("",file($add)); $opt = array ('complexType' => 'object','parseAttributes' => 'true','attribuesArray' => '_attributes'); $xml = new XML_Unserializer($opt); $xml -> unserialize($xmldoc, false); $xml = $xml->getUnserializedData(); mb_convert_encoding($xml, "SJIS","UTF-8"); print_r($xml->channel->item[1]->ldWeather:lwws);←ここが問題箇所 PHPを始めたばかりで説明に不十分な箇所があるかも知れませんが、よろしくお願い致します。 PHPバージョン:PHP Version 4.4.6 XML取得先:Livedoor Weather Web Service 利用目的:勉強の為

    • ベストアンサー
    • PHP
  • PHPでのXMLの編集・削除の方法

    XMLの編集・削除をPHPで行いたいと思っています。 その際に、どの要素なのかを指定したいと思うのですが なかなか方法が分からずに困っています。 調べてみて、Xpathを利用して指定し 削除をする時には DOMNode = DOMNode->removeChild(ノード) 編集する時には DOMNode->nodeValue = 値 と、いうものを利用すればいいのかな?と分かってきたのですが 実際、PHPに組み込んでみても、動いてくれず分からなくなっています。 【削除PHP】 foreach ($_POST['number'] as $key => $value){ $xpath = new DOMXPath($doc); $xpath_title = $xpath->query("//title[parent::record/@number=$value]"); //要素ノードの取得 $dataElement = $doc->getElementsByTagName("title")->item(0); //削除 $dataElement->removeChild($xpath_title) or die("削除できません。"); } 【編集PHP】 $xpath = new DOMXPath($doc); $xpath_title = $xpath->query("//record/@number=$session_number"); //値の変更 $session_title = $_SESSION["title"]; $xpath_title->title->nodeValue = $session_title; print $xpath_title->title->nodeValue; 【XML】 <renew>  <record number="000000">   <title>タイトル</title>   <paragraph>内容</paragraph>  </record> </renew> 字数制限の為に、コードも必要最低限だと思われるものしか 記述していません。これでは分からないという事であれば 追記で記述しますので、分かる方は是非教えてください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • XML::XPathを使う

    エラーがでて期待する出力が出ず困っています。 ファイル名とXPathのコマンドライン引数をとり、 指定されたパスに一致するノードを出力するものです。 (参考書の写しなので、記述ミスはないと思います。) ■grabber.pl use XML::XPath; use XML::XPath::XMLParser; my $xpath = XML::XPath->new( filename => shift @ARGV ); my $nodeset = $xpath->find( shift @ARGV ); foreach my $node ( nodeset->get_nodelist ) { print XML::XPath::XMLParser::as_string( $node ) . "\n"; } コマンドラインに入力しているものは、 perl grabber.pl data.xml "/inventory/category/item/name" ■data.xml <?xml version="1.0"?> <inventory date="2001"> <category> <item id="2"> <name>aaaa</name> </item> </category> </inventory> です。 perl grabber.pl data.xml "/inventory/category/item/name" としても、下記にエラーが出ます。 Can't locate object method "get_nodelist" via package "nodeset" (perhaps you for got to load "nodeset"?) at grabber.pl line 5. いろいろ試してみたり調べたのですが、 行き詰ってしまいました。 期待する出力は"<name>aaaa</name>"なのですが・・・ どなたかこのエラーの原因がおわかりになるかた いらっしゃいますでしょうか。 環境は以下になります。 ・windowsxp ・activePerl モジュールのインストール済み ・XML-XPath ・XML-Parser 以上です。

    • ベストアンサー
    • Perl
  • PHPパーサー MagpieRSSについて

    PHPパーサーのMagpieRSSを使用しています。 読み込むxmlが更新されてもそれが反映されません。 また、htmlとして書き出す際に<p>タグにid名を付けたいのですが、idをつけるとエラーがでます。これはPHPでは文法的にまずいんでしょうか?下記が使用しているソースです。 重ねて質問なんですが、下記のソースでは1つのxmlしか読み込んでいませんが、複数のxmlを読み込むにはどうしたらいいのでしょうか。 よろしくお願いします。 <?php require_once 'rss_fetch.inc'; require_once 'rss_utils.inc'; $url = 'http://www.xxxxx/xxxxxx/index.xml'; $rss = fetch_rss($url); $title = $rss->channel['title']; $title = mb_convert_encoding($title, "UTF-8", "auto"); $rss->items = array_slice($rss->items, 0, 1); foreach ($rss->items as $item ) { $description = $item[description]; $description = mb_convert_encoding($description, "UTF-8", "auto"); $url = $item[link]; $date = date("Y.m.d", $item['date_timestamp']); echo "$description?n"; } ?>

    • ベストアンサー
    • PHP
  • mysql_fetch_objectの書き方を教えて下さい。

    PHP5.1.6を使用しています。 次のスクリプトを書きましたが、データが取得できません。 $conn_id = mysql_connect("localhost","***","***") or die('Error connecting to MySQL'); mysql_select_db('***',$conn_id); $query ="SELECT abcd,efgh from XYZ where name='taro'"; $result = mysql_query($query,$conn_id) or die($query.'failed('.mysql_error().')'); $ydata = array(); $xdata = array(); while($row = mysql_fetch_array($result)){  ← 11行目 array_push($ydata, $row->efgh);   ← 12行目 array_push($xdata, $row->abcd);   ← 13行目 } エラーログを見ると、 PHP Notice: Trying to get property of non-object in /***/***/****.php on line 12 PHP Notice: Trying to get property of non-object in /***/***/****.php on line 13 となっています。 var_dump($row) 句を入れ、ブラウザから見ると、当然ながら(?)bool(false) と表示されます。 11行目の mysql_fetch_array を mysql_fetch_object に入れ換えて while($row = mysql_fetch_object($result)){ としても結果は変わりません。 リファレンスマニュアルやサンプルを参照して種々手直ししましたが、今ひとつ正解に辿り着けません。 データを取得して配列に入れるには、どのように修正すれば良いか、教えて頂けませんでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう