PHP: SimpleXML関数 - Manual
PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links | my php.net 
search for in the  
<shmop_writesimplexml_element->asXML>
view the version of this page
Last updated: Tue, 21 Dec 2004

CVIII. SimpleXML関数

導入

警告

このモジュールは、 実験的なものです。これは、これらの関数の動作、関 数名は、このドキュメントに書かれて事項と同様に告知なく将来的なPHPのリ リースで変更される可能性があります。注意を喚起するとともに、このモジュー ルは使用者のリスクで使用して下さい。

SimpleXML拡張モジュールは、 XMLをオブジェクトにとても簡単かつ容易に変換するための機能を 提供します。変換後のオブジェクトでは、 通常のプロパティセレクタや配列反復子を用いて処理を行うことが 可能です。

インストール手順

この拡張モジュールは、PHPの configure に --enable-simplexml を 指定して実行された場合のみ利用可能です。PHPのconfigureスクリプト はデフォルトでこれを行います。

このリファレンスの多くの例では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&#211;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>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
</movies>
XML;?>

SimpleXMLの容易さが最も明確に現われるのは、 簡単なXMLドキュメントから文字列または数字を展開する時です。

例 2. <plot> を取得する

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

echo
$xml->movie[0]->plot; // "So this language. It's like..."
?>

例 3. SimpleXMLでユニークでない要素にアクセスする

単一の親要素の子要素としてある要素のインスタンスが複数存在する時、 通常の反復処理を適用することができます。

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

/* For each <movie> node, we echo a separate <plot>. */
foreach ($xml->movie as $movie) {
   echo
$movie->plot, '<br />';
}

?>

例 4. 属性を使用する

ここまでは、要素の名前と値を読む方法のみを扱って来ました。 SimpleXMLは要素の属性にアクセスすることも可能です。 要素の属性にアクセスする方法は、配列 の要素に アクセスするのと全く同じです。

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

/* Access the <rating> nodes of the first movie.
 * Output the rating scale, too. */
foreach ($xml->movie[0]->rating as $rating) {
   switch((string)
$rating['type']) { // Get attributes as element indices
  
case 'thumbs':
       echo
$rating, ' thumbs up';
       break;
   case
'stars':
       echo
$rating, ' stars';
       break;
   }
}
?>

例 5. 要素および属性をテキストと比較する

要素または属性を文字列と比較する、もしくは、文字列を引数とする関数に 渡すには、(string) により文字列にキャストする 必要があります。さもないと、PHPはこの要素をオブジェクトとして扱います。

<?php   
include 'example.php';

$xml = simplexml_load_string($xmlstr);

if ((string)
$xml->movie->title == 'PHP: Behind the Parser') {
   print
'My favorite movie.';
}

htmlentities((string) $xml->movie->title);
?>

例 6. Xpathの使用

SimpleXMLには、Xpathをサポートしています。 <character> 要素を全て見つけるには、 以下のようにします。

<?php
include 'example.php';
$xml = simplexml_load_string($xmlstr);

foreach (
$xml->xpath('//character') as $character) {
   echo
$character->name, 'played by ', $character->actor, '<br />';
}
?>

'//' はワイルドカードとして動作します。絶対パスを指定するには、 スラッシュを一つだけにします。

例 7. 値を設定する

SimpleXMLの中のデータは、定数とすることができません。 オブジェクトは、その全ての要素について変更が可能です。

<?php
include 'example.php';
$xml = simplexml_load_string($xmlstr);

$xml->movie[0]->actor[0]->age = '21';

echo
$xml->asXML();
?>

上のコードは、元のXMLドキュメントと全く同じXMLドキュメントを新規に 出力しますが、新しいXMLファイルでは、Ms. Coderの年齢が21と定義されている ところが異なります。

例 8. 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;
?>

目次
simplexml_element->asXML --  SimpleXML要素に基づき整形式のXML文字列を返す
simplexml_element->attributes --  要素の属性を定義する
simplexml_element->children --  指定したノードの子ノードを見付ける
simplexml_element->xpath --  XMLデータにXpathクエリを実行する
simplexml_import_dom --  DOMノードからsimplexml_elementオブジェクトを取得する
simplexml_load_file --  XMLファイルをパースし、オブジェクトに代入する
simplexml_load_string --  XML文字列をオブジェクトに代入する


add a note add a note User Contributed Notes
SimpleXML関数
nelson_menezes at yahoo dot co dot uk
01-Mar-2005 01:05
Note that SimpleXML expects to both read and output XML in UTF-8 encoding. You'll need to add a line such as this at the top of your input XML file if it isn't saved in UTF-8 (adjust to whatever encoding used):

<?xml version="1.0" encoding="ISO-8859-1" ?>

On the output side of things, if you're not serving/handling UTF-8, you'll need to use utf8_decode(). Common mistake:
webmarks
14-Feb-2005 05:57
I'm new to PHP and XML, but I think others might pull their hair out over this too.  I forgot about XML and whitespace when I was populating an array with node values, and was getting what appeared to be duplicate values despite using array_unique(). Use trim() when populating an array or assigning a variable.

<?php
$xml_array
= array();
foreach (
$resource->xpath($node_match) as $option){
  
$xml_array[$i] = trim($option);
  
$i++;
}
$xml_unique_array = array_unique($xml_array);
?>
roland dot swingler at transversal dot com
08-Feb-2005 10:24
Just a quick note - if you wish to get the name of the tag you are operating on, use the the key bit of foreach, i.e in the example:

<?php
// Outputs title characters plot rating rating
foreach($xml->movie[0]->children() as $tag => $child){
  echo
$tag;
}
?>

This might seem obvious but it stumped me for a bit.
yannis dot haralambous at enst-bretagne dot fr
29-Jan-2005 08:44
Sometimes tag names do not respect PHP variable name syntax. For example I have a file like this:
<livre>
   <�ditorial>
     <�dition-originale ref="123">
         bla bla bla
     </�dition-originale>
   </�ditorial>
</livre>
It's a perfectly valid XML file, but
$livre->�ditorial[0]->�dition-originale[0]->attributes()
will not work because of the hyphen.

The only solution I found is to write:
$livre->�ditorial[0]->{"�dition-originale"}[0]->attributes()

$livre->xpath("/livre/�ditorial/�dition-originale/@ref") doesn't work either but for that one I don't know how to solve the problem...
Daniel FAIVRE - geomaticien.com
14-Jan-2005 11:46
I've searched a while for a convenient "to array" function, and finally wrote it. These one provide at least 5 cool features:
- the MOST IMPORTANT: return a correct structure when several childs nodes have the same name: nodes are numbered properly
- read CDATA values
- returned array is very easy-to-use
- attributes returned in sub-arrays with key [@]
- very fast

When you create a "xml2array" function, you need to manage  nodes with attributes, but without children: i've choosed to ignore their attributes to avoid a "virtual ['value'] node" for such nodes in the returned array.

<?php
/**
 * Convert SimpleXMLElement object to array
 * Copyright Daniel FAIVRE 2005 - www.geomaticien.com
 * Copyleft GPL license
 */

function simplexml2array($xml) {
   if (
get_class($xml) == 'SimpleXMLElement') {
      
$attributes = $xml->attributes();
       foreach(
$attributes as $k=>$v) {
           if (
$v) $a[$k] = (string) $v;
       }
      
$x = $xml;
      
$xml = get_object_vars($xml);
   }
   if (
is_array($xml)) {
       if (
count($xml) == 0) return (string) $x; // for CDATA
      
foreach($xml as $key=>$value) {
          
$r[$key] = simplexml2array($value);
       }
       if (isset(
$a)) $r['@'] = $a;    // Attributes
      
return $r;
   }
   return (string)
$xml;
}

?>
igor kraus
07-Jan-2005 06:37
A simple way to merge two SimpleXML objects.

<?php
/**
* Pumps all child elements of second SimpleXML object into first one.
*
* @param    object      $xml1  SimpleXML object
* @param    object      $xml2  SimpleXML object
* @return  void
*/
function simplexml_merge (SimpleXMLElement &$xml1, SimpleXMLElement $xml2)
{
  
// convert SimpleXML objects into DOM ones
  
$dom1 = new DomDocument();
  
$dom2 = new DomDocument();
  
$dom1->loadXML($xml1->asXML());
  
$dom2->loadXML($xml2->asXML());

  
// pull all child elements of second XML
  
$xpath = new domXPath($dom2);
  
$xpathQuery = $xpath->query('/*/*');
   for (
$i = 0; $i < $xpathQuery->length; $i++)
   {
      
// and pump them into first one
      
$dom1->documentElement->appendChild(
          
$dom1->importNode($xpathQuery->item($i), true));
   }
  
$xml1 = simplexml_import_dom($dom1);
}

$xml1 = simplexml_load_string('<root><child>child 1</child></root>');
$xml2 = simplexml_load_string('<root><child>child 2</child></root>');
simplexml_merge($xml1, $xml2);
echo(
$xml1->asXml());
?>

Will output:
<?xml version="1.0"?>
<root>
   <child>child 1</child>
   <child>child 2</child>
</root>
brcavanagh AT NO SPAM hotmail.com
03-Jan-2005 05:18
If you are looking to use SimpleXML for anything but reading XML documents, you should really reconsider, and use the XML DOM library.  By the time you get enough utilities implemented in DOM to handle all the set backs in SimpleXML, you will have defeated the purpose of using SimpleXML.  There are a few reasons for this, and there are already many workrounds, but the primairy issues are this

1) No complex node assignment.  You cannot switch nodes or replace them. 

2) No appending new child nodes

3) Whenever you do something like $new_node = $xml_doc->node you will always get a reference even if you use a clone method, which will crash the script.

Other than that, its a great tool for reading docs.
aidan at php dot net
24-Dec-2004 08:42
SimpleXML does support namespaces, however their use is not as "simple".

This article explains much about SimpleXML, the limitations and problems in supporting namespaces, and possible solutions.

aidan at php dot net
22-Dec-2004 07:20
SimpleXML doesn't allow the creation of new elements (nodes). However, we can use DOM as an intermediary.

This function allows you to add elements with SimpleXML:

lajos dot arpasi at maxxlogic dot hu
08-Oct-2004 12:31
If you use PHP4 and miss the features of SimpleXML try MiniXML ().
MiniXML is a PHP class library for generating and parsing XML.
MiniXML have similar abilities like creating XML files from Arrays and importing XML files into Arrays.
You can manipulate the XML files more easily than SimpleXML.
It saved my life:).
majkqball_gmail_com
25-Sep-2004 10:44
Converting SimpleXML objects to an array:

<?php
$sx
= simplexml_load_string('your xml string here');

function
recursive_obj2array($obj, &$subject_array=array()) {
   foreach ((array)
$obj as $key => $var) {
       if (
is_object($var)) {
           if(
count((array) $var) == 0) {
              
$subject_array[$key] = 'NULL';
           }
           else {
              
recursive_obj2array($var, $subject_array[$key]);
           }
       }
       else {
          
$subject_array[$key] = $var;
       }
   }
}

$gimmie = array();

recursive_obj2array($sx, $gimmie);
?>

Then $gimmie is foreach friendly.

Quick and dirty, but rather effective.
farzan ath ifarzan dod com
25-Sep-2004 10:38
You can access XML elements in a SimpleXML object using variables:

<?
$xml
= simplexml_loaf_file(...);

print
$xml->$element;
?>

or use functions:

<?
print $xml->{getLanguage()};
?>

Note: You Must use { and } or PHP would think you are calling a member function.
You can use members of other objects as well:

<?
print $xml->{$obj->var};
?>

As a real life example; I have used this statement in one of my projects:

<?
$x
= $xrules->listing->fieldtitles->$lang->{$obj->name}->title;
?>

As you see, using varialbes and functions as element names are posible in SimpleXML; Thanks to PHP5's object orientaion new features.
jam from Russia
24-Sep-2004 03:23
Example:
<?xml version="1.0"?>
<root status="ok">
   <login status="logining"/>
   <user:name xmlns:user="">jam</user:name>
</root>

You can get value from "user:name" element:
$user_name = $xml->xpath('/root/user:name');

You can get value from "status" attribute "root" element:
$status = $xml->xpath('/root/@status');

You can get value from "status" attribute "login" element:
$logined = $xml->xpath('/root/login/@status');

SimpleXML work with namespace :-)
cellog at php dot net
31-Aug-2004 11:11
simplexml does not simply handle CDATA sections in a foreach loop.

<?php
$sx
= simplexml_load_string('
<test>
 <one>hi</one>
 <two><![CDATA[stuff]]></two>
 <t>
  <for>two</for>
 </t>
 <multi>one</multi>
 <multi>two</multi>
</test>'
);
foreach((array)
$sx as $tagname => $val) {
   if (
is_string($val)) {
      
// <one> will go here
  
} elseif (is_array($val)) {
      
// <multi> will go here because it happens multiple times
  
} elseif (is_object($val)) {
    
// <t> will go here because it contains tags
     // <two> will go here because it contains CDATA!
  
}
}
?>

To test in the loop, do this

<?php
if (count((array) $val) == 0) {
  
// this is not a tag that contains other tags
  
$val = '' . $val;
  
// now the CDATA is revealed magically.
}
?>
bb at nospam xnull dot de
20-Jul-2004 10:39
the simplexml_to_array function below has a bug, if there are 2 or more fields, it get's bit out of control, here is the right one:

<?
function simplexml_to_array($xml) {
  
$ar = array();
   foreach(
$xml->children() as $k => $v) {
      
// recurse the child
      
$child = simplexml_to_array($v);
      
// if it's not an array, then it was empty, thus a value/string
      
if( count($child) == 0 ) {
          
$child = (string)$v;
       }

      
// add the childs attributes as if they where children
      
foreach( $v->attributes() as $ak => $av ) {
          
// if the child is not an array, transform it into one
          
if( !is_array( $child ) ) {
              
$child = array( "value" => $child );
           }
          
$child[$ak] = (string)$av;
       }

      
// if the $k is already in our children list, we need to transform
       // it into an array, else we add it as a value
      
if (!in_array($k,array_keys($ar))) {
          
$ar[$k] = $child;
       } elseif (@
in_array(0,@array_keys($ar[$k]))) {
          
$ar[$k][] = $child;
       } else {
          
$ar[$k] = array($ar[$k]);
          
$ar[$k][] = $child;
       }

   }
   return
$ar;
}
?>
rishad at kaluma dot com
01-Jul-2004 04:12
To test whether a child node exists I used the following code:

<?php

function child_exists($xml, $childpath)
{
  
$result = $xml->xpath($childpath);
   if (
count($result)) {
       return
true;
   } else {
       return
false;
   }
}

?>
philip
17-Jun-2004 10:58
A introductory tutorial on simplexml can be found here:
*
*
*
greg dot steffensen at spamless dot richmond dot edu
19-Feb-2004 11:04
Simplexml's simplicity can be deceptive.  Simplexml elements behave either as objects or strings, depending on the context in which they're used (through overloading of the __toString() method, I assume).  Statements implying conversion to string treat them as strings, while assignment operations treat them as objects.  This can lead to unexpected behavior if, for example, you are trying to compare the values of two Simplexml elements.  The expected syntax will not work.  To force conversion to strings, just "typecast' whatever Simplexml element you're using.  For example:

<?php
$s
= simplexml_load_string('<foo>43</foo> <bar>43</bar>');

// Evaluates to false by comparing object IDs instead of strings
($s->foo == $s->bar);

// Evaluates to true
((string)$s->foo == (string)$s->bar);
?>

[Ed. Note: Changed from quotes to casts because casts provide a quicker and more explicit conversion than do double quotes.]

<shmop_writesimplexml_element->asXML>
 Last updated: Tue, 21 Dec 2004
show source | credits | sitemap | contact | advertising | mirror sites 
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: /
Last updated: Mon Mar 14 08:13:06 2005 Local time zone must be set--see zic manual page