SimpleXMLElement クラス
(PHP 8)
はじめに
XML ドキュメントの要素をあらわします。
クラス概要
変更履歴
バージョン | 説明 |
---|---|
8.0.0 | SimpleXMLElement は、 Stringable, Countable, RecursiveIterator を新たに実装しました。 |
目次
- SimpleXMLElement::addAttribute — SimpleXML 要素に属性を追加する
- SimpleXMLElement::addChild — XML ノードに子要素を追加する
- SimpleXMLElement::asXML — SimpleXML 要素に基づき整形式の XML 文字列を返す
- SimpleXMLElement::attributes — 要素の属性を定義する
- SimpleXMLElement::children — 指定したノードの子ノードを見付ける
- SimpleXMLElement::__construct — 新しい SimpleXMLElement オブジェクトを作成する
- SimpleXMLElement::count — 子要素を数える
- SimpleXMLElement::current — 現在の要素を返す
- SimpleXMLElement::getDocNamespaces — ドキュメントで宣言されている名前空間を返す
- SimpleXMLElement::getName — XML 要素の名前を取得する
- SimpleXMLElement::getNamespaces — ドキュメントで使用している名前空間を返す
- SimpleXMLElement::getChildren — 現在の要素の子要素を返す
- SimpleXMLElement::hasChildren — 現在の要素が子要素を持つかどうかを調べる
- SimpleXMLElement::key — 現在のキーを返す
- SimpleXMLElement::next — 次の要素に移動する
- SimpleXMLElement::registerXPathNamespace — 次の XPath クエリ用の prefix/ns コンテキストを作成する
- SimpleXMLElement::rewind — 最初の要素に巻き戻す
- SimpleXMLElement::saveXML — SimpleXMLElement::asXML のエイリアス
- SimpleXMLElement::__toString — 文字列で要素の内容を返す
- SimpleXMLElement::valid — 現在の要素が有効かどうかを調べる
- SimpleXMLElement::xpath — XML データに Xpath クエリを実行する
+add a note
User Contributed Notes 27 notes
rmirabelle ¶
14 years ago
To further previous comments and drive the point home:
What makes SimpleXMLElement tricky to work with is that it feels and behaves like an object, but is actually a system RESOURCE, (specifically a libxml resource).
That's why you can't store a SimpleXMLElement to $_SESSION or perform straight comparison operations on node values without first casting them to some type of object. $_SESSION expects to store 'an object' and comparison operators expect to compare 2 'objects' and SimpleXMLElements are not objects.
When you echo or print a node's value, PHP converts the value (a resource) into a string object for you. It's a time saver for sure, but can fool you into thinking that your SimpleXMLElement is an object.
Hope this helps clarify
juanfhj at gmail dot spam dot me dot not dot com ¶
13 years ago
To access the underlying element as a string, it's necessary to make the cast $x = (string)$my_xml_element.
Anonymous ¶
13 years ago
Warning to anyone trying to parse XML with a key name that includes a hyphen ie.)
<subscribe>
<callback-url>example url</callback-url>
</subscribe>
In order to access the callback-url you will need to do something like the following:
<?php
$xml = simplexml_load_string($input);
$callback = $xml->{"callback-url"};
?>
If you attempt to do it without the curly braces and quotes you will find out that you are returned a 0 instead of what you want.
saganmarketing.com ¶
12 years ago
Parsing an invalid XML string through SimpleXML causes the script to crash completely (usually) therefore it is best to make sure the XML is valid before parsing with something like this:
// Must be tested with ===, as in if(isXML($xml) === true){}
// Returns the error message on improper XML
function isXML($xml){
libxml_use_internal_errors(true);
$doc = new DOMDocument('1.0', 'utf-8');
$doc->loadXML($xml);
$errors = libxml_get_errors();
if(empty($errors)){
return true;
}
$error = $errors[0];
if($error->level < 3){
return true;
}
$explodedxml = explode("r", $xml);
$badxml = $explodedxml[($error->line)-1];
$message = $error->message . ' at line ' . $error->line . '. Bad XML: ' . htmlentities($badxml);
return $message;
}
CameronXie ¶
7 years ago
Map xml to array (with attributes)
<?php declare(strict_types=1);
/**
* @param SimpleXMLElement $xml
* @return array
*/
function xmlToArray(SimpleXMLElement $xml): array
{
$parser = function (SimpleXMLElement $xml, array $collection = []) use (&$parser) {
$nodes = $xml->children();
$attributes = $xml->attributes();
if (0 !== count($attributes)) {
foreach ($attributes as $attrName => $attrValue) {
$collection['attributes'][$attrName] = strval($attrValue);
}
}
if (0 === $nodes->count()) {
$collection['value'] = strval($xml);
return $collection;
}
foreach ($nodes as $nodeName => $nodeValue) {
if (count($nodeValue->xpath('../' . $nodeName)) < 2) {
$collection[$nodeName] = $parser($nodeValue);
continue;
}
$collection[$nodeName][] = $parser($nodeValue);
}
return $collection;
};
return [
$xml->getName() => $parser($xml)
];
}
php at keith tyler dot com ¶
14 years ago
The root node element of your input XML string is not retrievable as a property.
<?php
$xml="<foo>bar</foo>";
$sxe=new SimpleXMLElement($xml);
print $sxe->foo;
?>
prints nothing. You can only get to the root element via the array index method ($sxe[0]).
Also, you may not have two (or more) root elements -- that is apparently not well-formed XML.
<?php
$xml="<foo/><bar/>";
$sxe=new SimpleXMLElement($xml);
?>
throws an exception. A Q&D is to append an arbitraty root node structure to both ends of the input:
<?php
$xml="<foo/><bar/>";
$sxe=new SimpleXMLElement("<z>".$xml."</z>");
?>
Doing this also solves the above problem of root node property accessibility. (It may not work if your XML string includes a declaration.)
Patanjali ¶
4 years ago
Further to rmirabelle's comment, to compare two SimpleXML elements, do the comparison between the objects returned by the dom_import_simplexml function, as per:
<?php
if(dom_import_simplexml($simplexml_element_1)===dom_import_simplexml($simplexml_element_2)){
...
}
?>
You must ensure that both are SimpleXML elements before conversion to DOM objects.
cherubangel at gmail dot com ¶
14 years ago
Note that changing attributes from within a foreach loop, especially namespaced attributes, can be very tricky.
For example, when trying to change the value of an existing xlink:href attribute:
<?php
foreach($xmlelement -> attributes('xlink', true) as $attribute => $attribvalue){
$attribvalue[0] = 'value'; // Throws an error
$attribvalue = 'value'; // Does not change your XML
$xmlelement -> addAttribute($attribute, 'value', 'http://www.w3.org/1999/xlink'); // Adds an attribute, does not change existing one.
$xmlelement[$attribute] = 'value'; // Adds an attribute, does not change existing one.
}
?>
Instead, you should access the array returned by the attributes() function directly, like this:
<?php
$xmlelement -> attributes('xlink', true) -> href = 'value'; // Works!
?>
heaver ¶
12 years ago
XML to JSON conversion without '@attributes'
<?php
function XML2JSON($xml) {
function normalizeSimpleXML($obj, &$result) {
$data = $obj;
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
foreach ($data as $key => $value) {
$res = null;
normalizeSimpleXML($value, $res);
if (($key == '@attributes') && ($key)) {
$result = $res;
} else {
$result[$key] = $res;
}
}
} else {
$result = $data;
}
}
normalizeSimpleXML(simplexml_load_string($xml), $result);
return json_encode($result);
}
?>
brett at brettbrewer dot com ¶
15 years ago
Figuring out how to access the properties of a SimpleXmlElement object was a little tricky for me. In particular, it took a while to discover that I needed to cast my SimpleXmlElement properties to be of type "string" to print them or do comparisons on them. For instance, assuming you already have a string of xml in $xmlstr...
<?php
$sxml= new SimpleXmlElement($xmlstr);
if ((string) $sxml->property== "somevalue") {
echo (string) $sxml->property;
}
?>
The properties of a SimpleXmlElement object are objects themselves, so you need to put "(string)" before them, which casts their values to a string instead of an object. I assume if you were doing a numeric comparison you'd want to cast to an (int) or something numeric instead.
ivandosreisandrade at gmail dot com ¶
15 years ago
Hello,
here goes my contribution for those whom are struggling to understand how SimpleXMLElement works.
After some time trying to figure out how this works, I've came up to this small example:
<?php
$xmlstr = "<?xml version='1.0' ?>\n".
// optionally you can specify a xml-stylesheet for presenting the results. just uncoment the following line and change the stylesheet name.
/* "<?xml-stylesheet type='text/xsl' href='xml_style.xsl' ?>\n". */
"<book></book>";
// create the SimpleXMLElement object with an empty <book> element
$xml = new SimpleXMLElement($xmlstr);
// add some child nodes
$xml->addChild("title", "Title of my book");
$xml->addChild("abstract", "My book is about learning to work with SimpleXMLElement");
// add some more child nodes
$chapter1 = $xml->addChild("chapter_1");
// add an attribute to child chapter_1
$chapter1->addAttribute("chapter_title", "Introduction to my book");
$chapter2 = $xml->addChild("chapter_2");
$chapter2->addAttribute("chapter_title", "Development of my book");
$chapter3 = $xml->addChild("chapter_3");
$chapter3->addAttribute("chapter_title", "Another chapter of my book");
$conclusion = $xml->addChild("conclusion", "The ending of my book");
// insert the header to tell the browser how to read the document
header("Content-type: text/xml");
// print the SimpleXMLElement as a XML well-formed string
echo $xml->asXML();
?>
With this script you can just copy-paste and try to understand how it works.
I hope it can help somebody :)