To take care of proper error checking, one must use try-catch blocks:
try {
$sxe = new SimpleXMLElement($xmlstring);
} catch (Exception $e) {
echo "bad xml";
}
To get rid of warnings, use @ in front of new:
try {
$sxe = @new SimpleXMLElement($xmlstring);
} catch (Exception $e) {
echo "bad xml";
}
例
このリファレンスの多くの例ではXML文字列を必要とします。各例で この文字列をくり返す代わりに、あるファイルにこの文字列を保存して、 各例で読みこむことにします。この読みこまれるファイルは、以下の例 に関するセクションで使用されます。 もしくは、XMLドキュメントを作成し、 simplexml_load_file() により読みこむことも 可能です。
例1 XML文字列を設定するインクルードファイル example.php
<?php
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
<title>PHP: Behind the Parser</title>
<characters>
<character>
<name>Ms. Coder</name>
<actor>Onlivia Actora</actor>
</character>
<character>
<name>Mr. Coder</name>
<actor>El ActÓr</actor>
</character>
</characters>
<plot>
So, this language. It's like, a programming language. Or is it a
scripting language? All is revealed in this thrilling horror spoof
of a documentary.
</plot>
<great-lines>
<line>PHP solves all my web problems</line>
</great-lines>
<rating type="thumbs">7</rating>
<rating type="stars">5</rating>
</movie>
</movies>
XML;
?>
SimpleXMLの容易さが最も明確に現われるのは、 簡単なXMLドキュメントから文字列または数字を展開する時です。
例2 <plot> を取得する
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
echo $xml->movie[0]->plot; // "So this language. It's like..."
?>
XML ドキュメント内の要素のうち、PHP の命名規約で許可されていない文字 (たとえばハイフンなど) を含む名前のものにアクセスするには、 要素名を括弧とアポストロフィで囲みます。
例3 <line> を取得する
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
echo $xml->movie->{'great-lines'}->line; // "PHP solves all my web problems"
?>
例4 SimpleXMLでユニークでない要素にアクセスする
単一の親要素の子要素としてある要素のインスタンスが複数存在する時、 通常の反復処理を適用することができます。
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
/* 個々の <movie> ノードに対して、<plot> を分割して表示します */
foreach ($xml->movie as $movie) {
echo $movie->plot, '<br />';
}
?>
例5 属性を使用する
ここまでは、要素の名前と値を読む方法のみを扱って来ました。 SimpleXMLは要素の属性にアクセスすることも可能です。 要素の属性にアクセスする方法は、配列 の要素に アクセスするのと全く同じです。
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
/* 最初の映画の <rating> ノードにアクセスします。
* また、その評価も出力します。*/
foreach ($xml->movie[0]->rating as $rating) {
switch((string) $rating['type']) { // 要素のインデックスとして、属性を取得します
case 'thumbs':
echo $rating, ' thumbs up';
break;
case 'stars':
echo $rating, ' stars';
break;
}
}
?>
例6 要素および属性をテキストと比較する
要素または属性を文字列と比較する、もしくは、文字列を引数とする関数に 渡すには、(string) により文字列にキャストする 必要があります。さもないと、PHPはこの要素をオブジェクトとして扱います。
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
if ((string) $xml->movie->title == 'PHP: Behind the Parser') {
print 'My favorite movie.';
}
htmlentities((string) $xml->movie->title);
?>
例7 XPath の使用
SimpleXML は、XPath を標準でサポートしています。 <character> 要素を全て見つけるには、 以下のようにします。
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
foreach ($xml->xpath('//character') as $character) {
echo $character->name, 'played by ', $character->actor, '<br />';
}
?>
'//' はワイルドカードとして動作します。絶対パスを指定するには、 スラッシュを一つだけにします。
例8 値を設定する
SimpleXMLの中のデータは、定数とすることができません。 オブジェクトは、その全ての要素について変更が可能です。
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
$xml->movie[0]->characters->character[0]->name = 'Miss Coder';
echo $xml->asXML();
?>
上のコードは、元のXMLドキュメントと全く同じXMLドキュメントを新規に 出力しますが、新しいXMLファイルでは、Ms. Coder が Miss Coder に変更されているところが異なります。
例9 要素と属性を追加する
PHP 5.1.3 以降では、SimpleXML を使用して簡単に子要素および属性を追加することができます。
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
$character = $xml->movie[0]->characters->addChild('character');
$character->addChild('name', 'Mr. Parser');
$character->addChild('actor', 'John Doe');
$rating = $xml->movie[0]->addChild('rating', 'PG');
$rating->addAttribute('type', 'mpaa');
echo $xml->asXML();
?>
上のコードは、元と同じオブジェクトを出力しますが、 そこに新しいキャラクターと評価が追加されています。
例10 DOMとの相互運用性
PHPは、SimpleXML形式とDOM形式の間でXMLノードを変換する機構を有しています。 この例では、DOM要素をSimpleXMLに変換することができます。
<?php
$dom = new domDocument;
$dom->loadXML('<books><book><title>blah</title></book></books>');
if (!$dom) {
echo 'Error while parsing the document';
exit;
}
$s = simplexml_import_dom($dom);
echo $s->book[0]->title;
?>
例
15-Aug-2008 05:17
04-May-2008 12:57
<?php
class QXML {
...
protected function _toXML(
$xmlArray,
$elmName='graph',
$elmCloseTag="",
$level=0)
{
$xmlString = "";
if(is_array($xmlArray)){
$strXmlAttributes = "";
$key_xml = "";
$keysXmlArray = array_keys($xmlArray);
$curLevel = $level + 1;
if(in_array(self::attribute,$keysXmlArray)){
if(isset($xmlArray[self::attribute])){
if(is_array($xmlArray[self::attribute])){
foreach($xmlArray[self::attribute]
as $xmlArrayKey => $xmlArrayValue)
{
$strXmlAttributes .= sprintf(' %s="%s"',
$xmlArrayKey,
addslashes($xmlArrayValue));
}
}
}
unset($xmlArray[self::attribute]);
}
if(in_array(self::textNode,$keysXmlArray)){
if(isset($xmlArray[self::textNode])){
if($xmlArray[self::textNode]){
$key_xml = $xmlArray[self::textNode];
}
if(strlen($ky_xml)){
$key_xml = sprintf("<![CDATA[%s]]>",$key_xml);
} else {
$key_xml = "";
}
}
unset($xmlArray[self::textNode]);
}
$keysXmlArray=array_keys($xmlArray);
if($elmCloseTag){
$indent=str_repeat(" ",$level * 5);
$xmlString .="\n".$indent.
"<".$elmCloseTag.$strXmlAttributes.">".
$key_xml;
}
if(is_array($xmlArray) && count($xmlArray)>0
&& count($keysXmlArray)>0)
{
reset($xmlArray);
foreach($keysXmlArray as $key){
$altKey = $altKeyXml = $xmlArray[$key];
$check = false;
foreach(array_keys($altKeyXml) as $j=>$p){
if(is_numeric($j)){
$check=true;
$xmlString.= $this->_toXML(
$altKeyXml[$j],
"",
$key,
$curLevel
);
unset($altKeyXml[$j]);
}
}
if($check){
$altKey = $altKeyXml;
}
if($altKey){
$xmlString .= $this->_toXML($altKey,"",$key,$curLevel);
}
}
}
if($elmCloseTag){
$xmlString.= (count($xmlArray)>0?"\n".$indent:"").
"</".$elmCloseTag.">";
}
}
if($elmName) {
$xmlString = "<?xml version='1.0' encoding='UTF-8'?>\n$xmlString\n";
}
return $xmlString;
}
...
}
?>
30-Apr-2008 09:52
@david b
@Fabi W
Why can't you use the ->{} operators?
e.g
$xml->{$node}
I've not tested this, but see no reason why it would not work.
24-Apr-2008 03:34
@david b's approach of dynamically accessing xml-elements:
You can explode the dynamic var with '->' as seperator and thus build a simple function to get the element
function simplexml_get_node_by_query($sxml_obj, $query)
{
$nodes = explode("->", $query);
$currTree = $sxml_obj;
foreach($nodes as $node)
{
$currTree = $currTree->$node;
}
return $currTree;
}
19-Apr-2008 12:11
It is important that you select the correct method of loading the XML in depending on the format of your XML file.
If you use the wrong function to load it in you will get some strange errors.
13-Apr-2008 06:04
Use eval() when using variable variables to access SimpleXML nodes.
e.g.
<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);
$s = 'movie[0]->plot' ;
echo "\n1: OK " . $xml->movie[0]->plot ; // OK
echo "\n2: FAIL " . $xml->$s ; // FAIL
echo "\n3: OK " . eval( "return \$xml->$s ;" ) ; // OK
?>
