Name('Rob') * ->Age('34') * ->Weight('185') * * to produce: * Rob * 34 * 185 * * - Add attributes to previous node using ->attribs : * $b->Person * ->attribs( array( * 'age' => 34, * 'weight' => 185, * )) * * to produce: * * * - 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]: * * * * * * * * - Add children to previous node using ->nest : * $b->People; * foreach (array('Rob','Casey','Brennen','Dave') as $name) * $b->nest( $b->child()->$name ); * * to produce: * * * * * * * * - 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:

. 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(); } }