<?php
|
|
namespace SparkLib\Xml;
|
|
|
|
use \DOMDocument, \DOMElement;
|
|
|
|
|
|
/** because DOMDocument sucks
|
|
*
|
|
* Builder is a wrapper for DOMDocument's creation interface.
|
|
*
|
|
* When using php's DOM library you are required to manually create a
|
|
* series of DOMInterface and DOMDocument and DOMAttribute and and and
|
|
* and and ...
|
|
*
|
|
* With SparkLib\Xml\Builder, you can instead just build out a series of
|
|
* nested nodes using a simplified method chaining syntax similar to
|
|
* XML builder clasess available elsewhere.
|
|
*
|
|
* SparkLib\Xml\Builder uses a subset of php's DOM functions so that
|
|
* the restrictions imposed by standard practice aren't enforced by
|
|
* the builder or DOM class.
|
|
*
|
|
* General usage:
|
|
* $b = new \SparkLib\Xml\Builder();
|
|
*
|
|
* - Create elements using the object operator:
|
|
* $b->Name('Rob')
|
|
* ->Age('34')
|
|
* ->Weight('185')
|
|
*
|
|
* to produce:
|
|
* <Name>Rob</Name>
|
|
* <Age>34</Age>
|
|
* <Weight>185</Weight>
|
|
*
|
|
* - Add attributes to previous node using ->attribs :
|
|
* $b->Person
|
|
* ->attribs( array(
|
|
* 'age' => 34,
|
|
* 'weight' => 185,
|
|
* ))
|
|
*
|
|
* to produce:
|
|
* <Person age="34" weight="185"></Person>
|
|
*
|
|
* - Build out an independent or nested set of nodes using ->child()
|
|
* and add them as children of a node :
|
|
* $people = $b->child();
|
|
* foreach (array('Rob','Casey','Brennen','Dave') as $name)
|
|
* $people->$name;
|
|
* $b->People($people);
|
|
*
|
|
* to produce[1]:
|
|
* <People>
|
|
* <Rob></Rob>
|
|
* <Casey></Casey>
|
|
* <Brennen></Brennen>
|
|
* <Dave></Dave>
|
|
* </People>
|
|
*
|
|
* - Add children to previous node using ->nest :
|
|
* $b->People;
|
|
* foreach (array('Rob','Casey','Brennen','Dave') as $name)
|
|
* $b->nest( $b->child()->$name );
|
|
*
|
|
* to produce:
|
|
* <People>
|
|
* <Rob></Rob>
|
|
* <Casey></Casey>
|
|
* <Brennen></Brennen>
|
|
* <Dave></Dave>
|
|
* </People>
|
|
*
|
|
* - Fetch a string representation of the document :
|
|
* print $b->People->Places->Things->string( $want_html );
|
|
*
|
|
* - Fetch the DOMDocument object for beating with hammers :
|
|
* $b->Youll->Hate->Yourself->domodc();
|
|
*
|
|
*
|
|
* Notes:
|
|
* 1: Thankfully, DOMDocument doesn't know how to create singleton tags,
|
|
* so it just creates empty tag pairs: <br></br>. D:
|
|
*/
|
|
|
|
class Builder {
|
|
private $domdoc;
|
|
private $namespace = '';
|
|
private $namespace_url = '';
|
|
|
|
private $last_node = false;
|
|
|
|
public function __construct(){
|
|
$this->domdoc = new DOMDocument('1.0');
|
|
}
|
|
|
|
public function attribs( $attributes ){
|
|
foreach ($attributes as $name => $value)
|
|
$this->last_node()->setAttribute($name, $value);
|
|
return $this;
|
|
}
|
|
|
|
public function child(){
|
|
$x = new static;
|
|
$x->xmlns($this->namespace, $this->namespace_url);
|
|
return $x;
|
|
}
|
|
|
|
public function nest($document){
|
|
if ($document == null)
|
|
return $this;
|
|
|
|
$node = $this->last_node();
|
|
|
|
if ($document instanceof DOMDocument)
|
|
$kids = $document;
|
|
elseif ($document instanceof static)
|
|
$kids = $document->domdoc;
|
|
else
|
|
throw new InvalidArgumentException(' nest only knows how to import children from a DOMDocument or a SparkLib\Xml\Builder.');
|
|
|
|
if (count($kids) == 0)
|
|
return $this;
|
|
|
|
foreach ($kids->childNodes as $kid) {
|
|
$node->appendChild(
|
|
$this->domdoc->importNode($kid, true)
|
|
);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function last_node(){
|
|
$node = $this->last_node;
|
|
|
|
if ($node === false)
|
|
throw new \LogicException('Unable to set attributes for nonexistant previous node');
|
|
|
|
return $node;
|
|
}
|
|
|
|
public function xmlns($namespace, $url){
|
|
$this->namespace = $namespace;
|
|
$this->namespace_url = $url;
|
|
return $this;
|
|
}
|
|
|
|
public function node($name, $value = '', $attributes = array(), $children = null){
|
|
if (strlen($this->namespace) > 0)
|
|
$node = new DOMElement("{$this->namespace}:{$name}", '', $this->namespace_url);
|
|
else
|
|
$node = new DOMElement($name);
|
|
|
|
$node->nodeValue = $value;
|
|
$this->last_node = $node;
|
|
|
|
$this->domdoc->appendChild($node);
|
|
|
|
$this->attribs($attributes);
|
|
$this->nest($children);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function __get($name){
|
|
$this->node($name);
|
|
return $this;
|
|
}
|
|
|
|
public function __call($name, $arguments){
|
|
if (count($arguments) <= 0) {
|
|
$this->node($name);
|
|
return $this;
|
|
}
|
|
|
|
$first = $arguments[0];
|
|
if ($first instanceof static)
|
|
$this->node($name, '', array(), $first->domdoc);
|
|
elseif ($first instanceof DOMDocument)
|
|
$this->node($name, '', array(), $first);
|
|
else
|
|
$this->node($name, $first);
|
|
return $this;
|
|
}
|
|
|
|
public function domdoc(){
|
|
return $this->domdoc;
|
|
}
|
|
|
|
public function string($html = false){
|
|
if ($html)
|
|
return $this->domdoc->saveHTML();
|
|
else
|
|
return $this->domdoc->saveXML();
|
|
}
|
|
}
|