-
Notifications
You must be signed in to change notification settings - Fork 20
SimpleXML Migration
If you worked with SimpleXML before the following examples should help you to understand FluentDOM. Like SimpleXML, FluentDOM uses PHP language features and interfaces to provide an easier and more compact syntax. Unlike SimpleXML, FluentDOM tries not to hide DOM, but to extend it. PHP itself implements DOM Level 2, FluentDOM adds DOM Level 3 methods.
The complete source of the following examples can be found in the repository: /examples/SimpleXML Migration.
FluentDOM::load()
returns an extended DOM document.
$element = simplexml_load_string($string);
echo $element->saveXML();
$element = simplexml_load_file($file);
echo $element->saveXML();
$document = FluentDOM::load($string);
echo $document->saveXML();
$document = FluentDOM::load($file, 'xml', [FluentDOM\Loader\Options::IS_FILE => TRUE]);
echo $document->saveXML();
$document = FluentDOM::load('<div/>', 'html');
echo $document->saveHTML();
$document = FluentDOM::load('{"foo": "bar"}', 'json');
echo $document->saveXML();
In SimpleXML you can use object property syntax to access the tag structure. The property can be cast to string to fetch the direct text children content.
$element = simplexml_load_string($xml);
echo $element->channel->title, "\n";
FluentDOM uses Xpath to accomplish that. Nodes can be used like functions to execute an Xpath expression in the context of the node. Xpath has a string cast built in.
$document = FluentDOM::load($xml);
echo $document('string(/rss/channel/title)'), "\n";
A problem with the object syntax is that it can result in error messages if an expected node structure does not exists.
$element = simplexml_load_string('<foo/>');
var_dump($element->some->other->element);
// PHP Notice: Trying to get property of non-object in
Using Xpath avoids the problem. If the location path returns and empty list, the result of the string cast will be an empty string.
$document = FluentDOM::load('<foo/>');
var_dump($document('string(/root/some/other/element)'));
// string(0) ""
You can use Xpath to validate if a node exists of course.
$document = FluentDOM::load('<foo/>');
var_dump($document('count(/root/some/other/element) > 0'));
// bool(false)
SimpleXML implements Traversable and __toString(). This allows to iterate nodes with foreach() and allow them to be cast into strings.
$element = simplexml_load_string($xml);
foreach ($element->channel->item as $item) {
echo $item->title, "\n";
}
FluentDOM depends heavily on XPath. If your Xpath expression is a location path it will return a node list, but using xpath functions, you can return strings, number or booleans.
$document = FluentDOM::load($xml);
foreach ($document('/rss/channel/item') as $item) {
echo $item('string(title)'), "\n";
}
The nodes it self implement __toString(), so they can be cast into a string.
$document = FluentDOM::load($xml);
foreach ($document('/rss/channel/item/title') as $title) {
echo $title, "\n";
}
SimpleXML allows to use Array Syntax to access the attribute of an element node.
$element = simplexml_load_string($xml);
echo $element['attribute'], "\n";
If you use a qualified name FluentDOM does also, ...
$element = FluentDOM::load($xml)->documentElement;
echo $element['attribute'], "\n";
... but if it is an integer it will access the child nodes.
$element = FluentDOM::load($xml)->documentElement[1];
echo $element->localName, "\n";
In SimpleXML the ->children() method allows access to an array containing the child elements
$element = simplexml_load_string($xml);
var_dump((string)$element->channel->children()[1]->title);
FluentDOM again uses Xpath. The expression results in a DOMNodelist object. It has methods to access its items and you can use iterator_to_array() to convert it into an array.
$document = FluentDOM::load($xml);
var_dump((string)$document('/rss/channel/item/title')->item(0));
Since PHP 5.6.3, DOMNodelist allows to use array syntax.
$document = FluentDOM::load($xml);
var_dump((string)$document('/rss/channel/item/title')[0]);
SimpleXMLs children() method is namespace aware. The first argument can a namespace uri or prefix (I suggest you always provide the namespace uri).
$element = simplexml_load_string($xml);
foreach ($element->children('http://www.w3.org/2005/Atom')->entry as $entry) {
echo $entry->children('http://www.w3.org/2005/Atom')->title, "\n";
}
Or use SimpleXML to fetch the nodes, the problem here is that you will have to register them again and again on each node.
$element = simplexml_load_string($xml);
$element->registerXPathNamespace('a', 'http://www.w3.org/2005/Atom');
foreach ($element->xpath('a:entry') as $entry) {
$entry->registerXPathNamespace('a', 'http://www.w3.org/2005/Atom');
echo $entry->xpath('a:title')[0], "\n";
}
In FluentDOM the namespaces can be registered on the document object. All node objects will have access to the registered namespaces.
$document = FluentDOM::load($xml);
$document->registerNamespace('a', 'http://www.w3.org/2005/Atom');
foreach ($document('/a:feed/a:entry') as $entry) {
echo $entry('string(a:title)'), "\n";
}
SimpleXML has some limited functionality for this, basically you can add child elements.
$element = simplexml_load_string('<ul/>');
$li = $element->addChild('li', 'FluentDOM');
$li['href'] = 'http://fluentdom.org';
echo $element->saveXml();
FluentDOM extends DOM for that, so you still can use all the DOM methods to create, insert and replace nodes.
DOMDocument::createElement()
is extended. It can resolve namespace prefixes and add attributes.
$document = new FluentDOM\DOM\Document();
$ul = $document->appendChild($document->createElement('ul'));
$li = $ul->appendChild(
$document->createElement('li', 'FluentDOM', ['href' => 'http://fluentdom.org'])
);
echo $document->saveHtml();
But here is a shortcut to add an element child.
$document = new FluentDOM\DOM\Document();
$ul = $document->appendElement('ul');
$li = $ul->appendElement('li', 'FluentDOM', ['href' => 'http://fluentdom.org']);
echo $document->saveHtml();
Additionally it has a dedicated API to create documents. The Creator is a function object. The first argument is the element name, the following arguments are attributes (array) or child nodes (scalars, nodes, ...). The calls can be nested, resulting in a really compact syntax.
Methods of the Creator allow to add special nodes like comments.
$_ = FluentDOM::create();
$document = $_(
'ul',
$_('li', ['href' => 'http://fluentdom.org'], 'FluentDOM')
)->document;
echo $document->saveHtml();
- Home
- Getting Started
- Tasks
- Plugins
- Functions
- Lists
- Creator (5.1)
- CSS Selectors
- Convertors
- Loaders
- Serializers (5.1)
- Transformers (5.1)
- Extended DOM
- XMLReader (6.1)
- XMLWriter (6.1)
- Interfaces