* @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2014 PradoSoft * @license http://www.pradosoft.com/license/ * @package Prado\Xml */ namespace Prado\Xml; use Prado\Exceptions\TIOException; /** * TXmlDocument class. * * TXmlDocument represents a DOM representation of an XML file. * Besides all properties and methods inherited from {@link TXmlElement}, * you can load an XML file or string by {@link loadFromFile} or {@link loadFromString}. * You can also get the version and encoding of the XML document by * the Version and Encoding properties. * * To construct an XML string, you may do the following: * * $doc=new TXmlDocument('1.0','utf-8'); * $doc->TagName='Root'; * * $proc=new TXmlElement('Proc'); * $proc->setAttribute('Name','xxxx'); * $doc->Elements[]=$proc; * * $query=new TXmlElement('Query'); * $query->setAttribute('ID','xxxx'); * $proc->Elements[]=$query; * * $attr=new TXmlElement('Attr'); * $attr->setAttribute('Name','aaa'); * $attr->Value='1'; * $query->Elements[]=$attr; * * $attr=new TXmlElement('Attr'); * $attr->setAttribute('Name','bbb'); * $attr->Value='1'; * $query->Elements[]=$attr; * * The above code represents the following XML string: * * * * * * 1 * 1 * * * * * * @author Qiang Xue * @package Prado\Xml * @since 3.0 */ class TXmlDocument extends TXmlElement { /** * @var string version of this XML document */ private $_version; /** * @var string encoding of this XML document */ private $_encoding; /** * Constructor. * @param string version of this XML document * @param string encoding of this XML document */ public function __construct($version='1.0',$encoding='') { parent::__construct(''); $this->setVersion($version); $this->setEncoding($encoding); } /** * @return string version of this XML document */ public function getVersion() { return $this->_version; } /** * @param string version of this XML document */ public function setVersion($version) { $this->_version=$version; } /** * @return string encoding of this XML document */ public function getEncoding() { return $this->_encoding; } /** * @param string encoding of this XML document */ public function setEncoding($encoding) { $this->_encoding=$encoding; } /** * Loads and parses an XML document. * @param string the XML file path * @return boolean whether the XML file is parsed successfully * @throws TIOException if the file fails to be opened. */ public function loadFromFile($file) { if(($str=@file_get_contents($file))!==false) return $this->loadFromString($str); else throw new TIOException('xmldocument_file_read_failed',$file); } /** * Loads and parses an XML string. * The version and encoding will be determined based on the parsing result. * @param string the XML string * @return boolean whether the XML string is parsed successfully */ public function loadFromString($string) { // TODO: since PHP 5.1, we can get parsing errors and throw them as exception $doc=new \DOMDocument(); if($doc->loadXML($string)===false) return false; $this->setEncoding($doc->encoding); $this->setVersion($doc->version); $element=$doc->documentElement; $this->setTagName($element->tagName); $this->setValue($element->nodeValue); $elements=$this->getElements(); $attributes=$this->getAttributes(); $elements->clear(); $attributes->clear(); static $bSimpleXml; if($bSimpleXml === null) $bSimpleXml = (boolean)function_exists('simplexml_load_string'); if($bSimpleXml) { $simpleDoc = simplexml_load_string($string); $docNamespaces = $simpleDoc->getDocNamespaces(false); $simpleDoc = null; foreach($docNamespaces as $prefix => $uri) { if($prefix === '') $attributes->add('xmlns', $uri); else $attributes->add('xmlns:'.$prefix, $uri); } } foreach($element->attributes as $name=>$attr) $attributes->add(($attr->prefix === '' ? '' : $attr->prefix . ':') .$name,$attr->value); foreach($element->childNodes as $child) { if($child instanceof \DOMElement) $elements->add($this->buildElement($child)); } return true; } /** * Saves this XML document as an XML file. * @param string the name of the file to be stored with XML output * @throws TIOException if the file cannot be written */ public function saveToFile($file) { if(($fw=fopen($file,'w'))!==false) { fwrite($fw,$this->saveToString()); fclose($fw); } else throw new TIOException('xmldocument_file_write_failed',$file); } /** * Saves this XML document as an XML string * @return string the XML string of this XML document */ public function saveToString() { $version=empty($this->_version)?' version="1.0"':' version="'.$this->_version.'"'; $encoding=empty($this->_encoding)?'':' encoding="'.$this->_encoding.'"'; return "\n".$this->toString(0); } /** * Magic-method override. Called whenever this document is used as a string. * * $document = new TXmlDocument(); * $document->TagName = 'root'; * echo $document; * * or * * $document = new TXmlDocument(); * $document->TagName = 'root'; * $xml = (string)$document; * * @return string string representation of this document */ public function __toString() { return $this->saveToString(); } /** * Recursively converts DOM XML nodes into TXmlElement * @param DOMXmlNode the node to be converted * @return TXmlElement the converted TXmlElement */ protected function buildElement($node) { $element=new TXmlElement($node->tagName); $element->setValue($node->nodeValue); foreach($node->attributes as $name=>$attr) $element->getAttributes()->add(($attr->prefix === '' ? '' : $attr->prefix . ':') . $name,$attr->value); foreach($node->childNodes as $child) { if($child instanceof \DOMElement) $element->getElements()->add($this->buildElement($child)); } return $element; } }