name = $name; if ($namespace) { $this->namespace = $namespace; } if (is_array($value) || is_object($value)) { $this->normalize($value); } elseif (!empty($value) || $value === 0 || $value === '0') { $this->createTextNode($value); } } /** * Adds a namespace to the current node * * @param string $prefix The namespace prefix * @param string $url The namespace DTD URL * @return void */ function addNamespace($prefix, $url) { if ($ns = Xml::addGlobalNs($prefix, $url)) { $this->namespaces = array_merge($this->namespaces, $ns); return true; } return false; } /** * Adds a namespace to the current node * * @param string $prefix The namespace prefix * @param string $url The namespace DTD URL * @return void */ function removeNamespace($prefix) { if (Xml::removeGlobalNs($prefix)) { return true; } return false; } /** * Creates an XmlNode object that can be appended to this document or a node in it * * @param string $name Node name * @param string $value Node value * @param string $namespace Node namespace * @return object XmlNode */ function &createNode($name = null, $value = null, $namespace = false) { $node =& new XmlNode($name, $value, $namespace); $node->setParent($this); return $node; } /** * Creates an XmlElement object that can be appended to this document or a node in it * * @param string $name Element name * @param string $value Element value * @param array $attributes Element attributes * @param string $namespace Node namespace * @return object XmlElement */ function &createElement($name = null, $value = null, $attributes = array(), $namespace = false) { $element =& new XmlElement($name, $value, $attributes, $namespace); $element->setParent($this); return $element; } /** * Creates an XmlTextNode object that can be appended to this document or a node in it * * @param string $value Node value * @return object XmlTextNode */ function &createTextNode($value = null) { $node = new XmlTextNode($value); $node->setParent($this); return $node; } /** * Gets the XML element properties from an object. * * @param object $object Object to get properties from * @return array Properties from object * @access public */ function normalize($object, $keyName = null, $options = array()) { if (is_a($object, 'XmlNode')) { return $object; } $name = null; $options += array('format' => 'attributes'); if ($keyName !== null && !is_numeric($keyName)) { $name = $keyName; } elseif (!empty($object->_name_)) { $name = $object->_name_; } elseif (isset($object->name)) { $name = $object->name; } elseif ($options['format'] == 'attributes') { $name = get_class($object); } $tagOpts = $this->__tagOptions($name); if ($tagOpts === false) { return; } if (isset($tagOpts['name'])) { $name = $tagOpts['name']; } elseif ($name != strtolower($name) && $options['slug'] !== false) { $name = Inflector::slug(Inflector::underscore($name)); } if (!empty($name)) { $node =& $this->createElement($name); } else { $node =& $this; } $namespace = array(); $attributes = array(); $children = array(); $chldObjs = array(); if (is_object($object)) { $chldObjs = get_object_vars($object); } elseif (is_array($object)) { $chldObjs = $object; } elseif (!empty($object) || $object === 0 || $object === '0') { $node->createTextNode($object); } $attr = array(); if (isset($tagOpts['attributes'])) { $attr = $tagOpts['attributes']; } if (isset($tagOpts['value']) && isset($chldObjs[$tagOpts['value']])) { $node->createTextNode($chldObjs[$tagOpts['value']]); unset($chldObjs[$tagOpts['value']]); } $n = $name; if (isset($chldObjs['_name_'])) { $n = null; unset($chldObjs['_name_']); } $c = 0; foreach ($chldObjs as $key => $val) { if (in_array($key, $attr) && !is_object($val) && !is_array($val)) { $attributes[$key] = $val; } else { if (!isset($tagOpts['children']) || $tagOpts['children'] === array() || (is_array($tagOpts['children']) && in_array($key, $tagOpts['children']))) { if (!is_numeric($key)) { $n = $key; } if (is_array($val)) { foreach ($val as $n2 => $obj2) { if (is_numeric($n2)) { $n2 = $n; } $node->normalize($obj2, $n2, $options); } } else { if (is_object($val)) { $node->normalize($val, $n, $options); } elseif ($options['format'] == 'tags' && $this->__tagOptions($key) !== false) { $tmp =& $node->createElement($key); if (!empty($val) || $val === 0 || $val === '0') { $tmp->createTextNode($val); } } elseif ($options['format'] == 'attributes') { $node->addAttribute($key, $val); } } } } $c++; } if (!empty($name)) { return $node; } return $children; } /** * Gets the tag-specific options for the given node name * * @param string $name XML tag name * @param string $option The specific option to query. Omit for all options * @return mixed A specific option value if $option is specified, otherwise an array of all options * @access private */ function __tagOptions($name, $option = null) { if (isset($this->__tags[$name])) { $tagOpts = $this->__tags[$name]; } elseif (isset($this->__tags[strtolower($name)])) { $tagOpts = $this->__tags[strtolower($name)]; } else { return null; } if ($tagOpts === false) { return false; } if (empty($option)) { return $tagOpts; } if (isset($tagOpts[$option])) { return $tagOpts[$option]; } return null; } /** * Returns the fully-qualified XML node name, with namespace * * @access public */ function name() { if (!empty($this->namespace)) { $_this =& XmlManager::getInstance(); if (!isset($_this->options['verifyNs']) || !$_this->options['verifyNs'] || in_array($this->namespace, array_keys($_this->namespaces))) { return $this->namespace . ':' . $this->name; } } return $this->name; } /** * Sets the parent node of this XmlNode. * * @access public */ function setParent(&$parent) { if (strtolower(get_class($this)) == 'xml') { return; } if (isset($this->__parent) && is_object($this->__parent)) { if ($this->__parent->compare($parent)) { return; } foreach ($this->__parent->children as $i => $child) { if ($this->compare($child)) { array_splice($this->__parent->children, $i, 1); break; } } } if ($parent == null) { unset($this->__parent); } else { $parent->children[] =& $this; $this->__parent =& $parent; } } /** * Returns a copy of self. * * @return object Cloned instance * @access public */ function cloneNode() { return clone($this); } /** * Compares $node to this XmlNode object * * @param object An XmlNode or subclass instance * @return boolean True if the nodes match, false otherwise * @access public */ function compare($node) { $keys = array(get_object_vars($this), get_object_vars($node)); return ($keys[0] === $keys[1]); } /** * Append given node as a child. * * @param object $child XmlNode with appended child * @param array $options XML generator options for objects and arrays * @return object A reference to the appended child node * @access public */ function &append(&$child, $options = array()) { if (empty($child)) { $return = false; return $return; } if (is_object($child)) { if ($this->compare($child)) { trigger_error(__('Cannot append a node to itself.', true)); $return = false; return $return; } } else if (is_array($child)) { $child = Set::map($child); if (is_array($child)) { if (!is_a(current($child), 'XmlNode')) { foreach ($child as $i => $childNode) { $child[$i] = $this->normalize($childNode, null, $options); } } else { foreach ($child as $childNode) { $this->append($childNode, $options); } } return $child; } } else { $attributes = array(); if (func_num_args() >= 2) { $attributes = func_get_arg(1); } $child =& $this->createNode($child, null, $attributes); } $child = $this->normalize($child, null, $options); if (empty($child->namespace) && !empty($this->namespace)) { $child->namespace = $this->namespace; } if (is_a($child, 'XmlNode')) { $child->setParent($this); } return $child; } /** * Returns first child node, or null if empty. * * @return object First XmlNode * @access public */ function &first() { if (isset($this->children[0])) { return $this->children[0]; } else { $return = null; return $return; } } /** * Returns last child node, or null if empty. * * @return object Last XmlNode * @access public */ function &last() { if (count($this->children) > 0) { return $this->children[count($this->children) - 1]; } else { $return = null; return $return; } } /** * Returns child node with given ID. * * @param string $id Name of child node * @return object Child XmlNode * @access public */ function &child($id) { $null = null; if (is_int($id)) { if (isset($this->children[$id])) { return $this->children[$id]; } else { return null; } } elseif (is_string($id)) { for ($i = 0; $i < count($this->children); $i++) { if ($this->children[$i]->name == $id) { return $this->children[$i]; } } } return $null; } /** * Gets a list of childnodes with the given tag name. * * @param string $name Tag name of child nodes * @return array An array of XmlNodes with the given tag name * @access public */ function children($name) { $nodes = array(); $count = count($this->children); for ($i = 0; $i < $count; $i++) { if ($this->children[$i]->name == $name) { $nodes[] =& $this->children[$i]; } } return $nodes; } /** * Gets a reference to the next child node in the list of this node's parent. * * @return object A reference to the XmlNode object * @access public */ function &nextSibling() { $null = null; $count = count($this->__parent->children); for ($i = 0; $i < $count; $i++) { if ($this->__parent->children[$i] == $this) { if ($i >= $count - 1 || !isset($this->__parent->children[$i + 1])) { return $null; } return $this->__parent->children[$i + 1]; } } return $null; } /** * Gets a reference to the previous child node in the list of this node's parent. * * @return object A reference to the XmlNode object * @access public */ function &previousSibling() { $null = null; $count = count($this->__parent->children); for ($i = 0; $i < $count; $i++) { if ($this->__parent->children[$i] == $this) { if ($i == 0 || !isset($this->__parent->children[$i - 1])) { return $null; } return $this->__parent->children[$i - 1]; } } return $null; } /** * Returns parent node. * * @return object Parent XmlNode * @access public */ function &parent() { return $this->__parent; } /** * Returns the XML document to which this node belongs * * @return object Parent XML object * @access public */ function &document() { $document =& $this; while (true) { if (get_class($document) == 'Xml' || $document == null) { break; } $document =& $document->parent(); } return $document; } /** * Returns true if this structure has child nodes. * * @return bool * @access public */ function hasChildren() { if (is_array($this->children) && !empty($this->children)) { return true; } return false; } /** * Returns this XML structure as a string. * * @return string String representation of the XML structure. * @access public */ function toString($options = array(), $depth = 0) { if (is_int($options)) { $depth = $options; $options = array(); } $defaults = array('cdata' => true, 'whitespace' => false, 'convertEntities' => false, 'showEmpty' => true, 'leaveOpen' => false); $options = array_merge($defaults, Xml::options(), $options); $tag = !(strpos($this->name, '#') === 0); $d = ''; if ($tag) { if ($options['whitespace']) { $d .= str_repeat("\t", $depth); } $d .= '<' . $this->name(); if (!empty($this->namespaces) > 0) { foreach ($this->namespaces as $key => $val) { $val = str_replace('"', '\"', $val); $d .= ' xmlns:' . $key . '="' . $val . '"'; } } $parent =& $this->parent(); if ($parent->name === '#document' && !empty($parent->namespaces)) { foreach ($parent->namespaces as $key => $val) { $val = str_replace('"', '\"', $val); $d .= ' xmlns:' . $key . '="' . $val . '"'; } } if (is_array($this->attributes) && !empty($this->attributes)) { foreach ($this->attributes as $key => $val) { if (is_bool($val) && $val === false) { $val = 0; } $d .= ' ' . $key . '="' . htmlspecialchars($val, ENT_QUOTES, Configure::read('App.encoding')) . '"'; } } } if (!$this->hasChildren() && empty($this->value) && $this->value !== 0 && $tag) { if (!$options['leaveOpen']) { $d .= ' />'; } if ($options['whitespace']) { $d .= "\n"; } } elseif ($tag || $this->hasChildren()) { if ($tag) { $d .= '>'; } if ($this->hasChildren()) { if ($options['whitespace']) { $d .= "\n"; } $count = count($this->children); $cDepth = $depth + 1; for ($i = 0; $i < $count; $i++) { $d .= $this->children[$i]->toString($options, $cDepth); } if ($tag) { if ($options['whitespace'] && $tag) { $d .= str_repeat("\t", $depth); } if (!$options['leaveOpen']) { $d .= 'name() . '>'; } if ($options['whitespace']) { $d .= "\n"; } } } } return $d; } /** * Return array representation of current object. * * @param boolean $camelize true will camelize child nodes, false will not alter node names * @return array Array representation * @access public */ function toArray($camelize = true) { $out = $this->attributes; foreach ($this->children as $child) { $key = $camelize ? Inflector::camelize($child->name) : $child->name; $leaf = false; if (is_a($child, 'XmlTextNode')) { $out['value'] = $child->value; continue; } elseif (isset($child->children[0]) && is_a($child->children[0], 'XmlTextNode')) { $value = $child->children[0]->value; if ($child->attributes) { $value = array_merge(array('value' => $value), $child->attributes); } if (count($child->children) == 1) { $leaf = true; } } elseif (count($child->children) === 0 && $child->value == '') { $value = $child->attributes; if (empty($value)) { $leaf = true; } } else { $value = $child->toArray($camelize); } if (isset($out[$key])) { if(!isset($out[$key][0]) || !is_array($out[$key]) || !is_int(key($out[$key]))) { $out[$key] = array($out[$key]); } $out[$key][] = $value; } elseif (isset($out[$child->name])) { $t = $out[$child->name]; unset($out[$child->name]); $out[$key] = array($t); $out[$key][] = $value; } elseif ($leaf) { $out[$child->name] = $value; } else { $out[$key] = $value; } } return $out; } /** * Returns data from toString when this object is converted to a string. * * @return string String representation of this structure. * @access private */ function __toString() { return $this->toString(); } /** * Debug method. Deletes the parent. Also deletes this node's children, * if given the $recursive parameter. * * @param boolean $recursive Recursively delete elements. * @access protected */ function _killParent($recursive = true) { unset($this->__parent, $this->_log); if ($recursive && $this->hasChildren()) { for ($i = 0; $i < count($this->children); $i++) { $this->children[$i]->_killParent(true); } } } } /** * Main XML class. * * Parses and stores XML data, representing the root of an XML document * * @package cake * @subpackage cake.cake.libs * @since CakePHP v .0.10.3.1400 */ class Xml extends XmlNode { /** * Resource handle to XML parser. * * @var resource * @access private */ var $__parser; /** * File handle to XML indata file. * * @var resource * @access private */ var $__file; /** * Raw XML string data (for loading purposes) * * @var string * @access private */ var $__rawData = null; /** * XML document header * * @var string * @access private */ var $__header = null; /** * Default array keys/object properties to use as tag names when converting objects or array * structures to XML. Set by passing $options['tags'] to this object's constructor. * * @var array * @access private */ var $__tags = array(); /** * XML document version * * @var string * @access private */ var $version = '1.0'; /** * XML document encoding * * @var string * @access private */ var $encoding = 'UTF-8'; /** * Constructor. Sets up the XML parser with options, gives it this object as * its XML object, and sets some variables. * * ### Options * - 'root': The name of the root element, defaults to '#document' * - 'version': The XML version, defaults to '1.0' * - 'encoding': Document encoding, defaults to 'UTF-8' * - 'namespaces': An array of namespaces (as strings) used in this document * - 'format': Specifies the format this document converts to when parsed or * rendered out as text, either 'attributes' or 'tags', defaults to 'attributes' * - 'tags': An array specifying any tag-specific formatting options, indexed * by tag name. See XmlNode::normalize(). * - 'slug': A boolean to indicate whether or not you want the string version of the XML document * to have its tags run through Inflector::slug(). Defaults to true * * @param mixed $input The content with which this XML document should be initialized. Can be a * string, array or object. If a string is specified, it may be a literal XML * document, or a URL or file path to read from. * @param array $options Options to set up with, for valid options see above: * @see XmlNode::normalize() */ function __construct($input = null, $options = array()) { $defaults = array( 'root' => '#document', 'tags' => array(), 'namespaces' => array(), 'version' => '1.0', 'encoding' => 'UTF-8', 'format' => 'attributes', 'slug' => true ); $options = array_merge($defaults, Xml::options(), $options); foreach (array('version', 'encoding', 'namespaces') as $key) { $this->{$key} = $options[$key]; } $this->__tags = $options['tags']; parent::__construct('#document'); if ($options['root'] !== '#document') { $Root =& $this->createNode($options['root']); } else { $Root =& $this; } if (!empty($input)) { if (is_string($input)) { $Root->load($input); } elseif (is_array($input) || is_object($input)) { $Root->append($input, $options); } } } /** * Initialize XML object from a given XML string. Returns false on error. * * @param string $input XML string, a path to a file, or an HTTP resource to load * @return boolean Success * @access public */ function load($input) { if (!is_string($input)) { return false; } $this->__rawData = null; $this->__header = null; if (strstr($input, "<")) { $this->__rawData = $input; } elseif (strpos($input, 'http://') === 0 || strpos($input, 'https://') === 0) { App::import('Core', 'HttpSocket'); $socket = new HttpSocket(); $this->__rawData = $socket->get($input); } elseif (file_exists($input)) { $this->__rawData = file_get_contents($input); } else { trigger_error(__('XML cannot be read', true)); return false; } return $this->parse(); } /** * Parses and creates XML nodes from the __rawData property. * * @return boolean Success * @access public * @see Xml::load() * @todo figure out how to link attributes and namespaces */ function parse() { $this->__initParser(); $this->__rawData = trim($this->__rawData); $this->__header = trim(str_replace( array('<' . '?', '?' . '>'), array('', ''), substr($this->__rawData, 0, strpos($this->__rawData, '?' . '>')) )); xml_parse_into_struct($this->__parser, $this->__rawData, $vals); $xml =& $this; $count = count($vals); for ($i = 0; $i < $count; $i++) { $data = $vals[$i]; $data += array('tag' => null, 'value' => null, 'attributes' => array()); switch ($data['type']) { case "open" : $xml =& $xml->createElement($data['tag'], $data['value'], $data['attributes']); break; case "close" : $xml =& $xml->parent(); break; case "complete" : $xml->createElement($data['tag'], $data['value'], $data['attributes']); break; case 'cdata': $xml->createTextNode($data['value']); break; } } xml_parser_free($this->__parser); $this->__parser = null; return true; } /** * Initializes the XML parser resource * * @return void * @access private */ function __initParser() { if (empty($this->__parser)) { $this->__parser = xml_parser_create(); xml_set_object($this->__parser, $this); xml_parser_set_option($this->__parser, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($this->__parser, XML_OPTION_SKIP_WHITE, 1); } } /** * Returns a string representation of the XML object * * @param mixed $options If boolean: whether to include the XML header with the document * (defaults to true); if an array, overrides the default XML generation options * @return string XML data * @access public * @deprecated * @see Xml::toString() */ function compose($options = array()) { return $this->toString($options); } /** * If debug mode is on, this method echoes an error message. * * @param string $msg Error message * @param integer $code Error code * @param integer $line Line in file * @access public */ function error($msg, $code = 0, $line = 0) { if (Configure::read('debug')) { echo $msg . " " . $code . " " . $line; } } /** * Returns a string with a textual description of the error code, or FALSE if no description was found. * * @param integer $code Error code * @return string Error message * @access public */ function getError($code) { $r = @xml_error_string($code); return $r; } // Overridden functions from superclass /** * Get next element. NOT implemented. * * @return object * @access public */ function &next() { $return = null; return $return; } /** * Get previous element. NOT implemented. * * @return object * @access public */ function &previous() { $return = null; return $return; } /** * Get parent element. NOT implemented. * * @return object * @access public */ function &parent() { $return = null; return $return; } /** * Adds a namespace to the current document * * @param string $prefix The namespace prefix * @param string $url The namespace DTD URL * @return void */ function addNamespace($prefix, $url) { if ($count = count($this->children)) { for ($i = 0; $i < $count; $i++) { $this->children[$i]->addNamespace($prefix, $url); } return true; } return parent::addNamespace($prefix, $url); } /** * Removes a namespace to the current document * * @param string $prefix The namespace prefix * @return void */ function removeNamespace($prefix) { if ($count = count($this->children)) { for ($i = 0; $i < $count; $i++) { $this->children[$i]->removeNamespace($prefix); } return true; } return parent::removeNamespace($prefix); } /** * Return string representation of current object. * * @return string String representation * @access public */ function toString($options = array()) { if (is_bool($options)) { $options = array('header' => $options); } $defaults = array('header' => false, 'encoding' => $this->encoding); $options = array_merge($defaults, Xml::options(), $options); $data = parent::toString($options, 0); if ($options['header']) { if (!empty($this->__header)) { return $this->header($this->__header) . "\n" . $data; } return $this->header() . "\n" . $data; } return $data; } /** * Return a header used on the first line of the xml file * * @param mixed $attrib attributes of the header element * @return string formated header */ function header($attrib = array()) { $header = 'xml'; if (is_string($attrib)) { $header = $attrib; } else { $attrib = array_merge(array('version' => $this->version, 'encoding' => $this->encoding), $attrib); foreach ($attrib as $key=>$val) { $header .= ' ' . $key . '="' . $val . '"'; } } return '<' . '?' . $header . ' ?' . '>'; } /** * Destructor, used to free resources. * * @access private */ function __destruct() { $this->_killParent(true); } /** * Adds a namespace to any XML documents generated or parsed * * @param string $name The namespace name * @param string $url The namespace URI; can be empty if in the default namespace map * @return boolean False if no URL is specified, and the namespace does not exist * default namespace map, otherwise true * @access public * @static */ function addGlobalNs($name, $url = null) { $_this =& XmlManager::getInstance(); if ($ns = Xml::resolveNamespace($name, $url)) { $_this->namespaces = array_merge($_this->namespaces, $ns); return $ns; } return false; } /** * Resolves current namespace * * @param string $name * @param string $url * @return array */ function resolveNamespace($name, $url) { $_this =& XmlManager::getInstance(); if ($url == null && isset($_this->defaultNamespaceMap[$name])) { $url = $_this->defaultNamespaceMap[$name]; } elseif ($url == null) { return false; } if (!strpos($url, '://') && isset($_this->defaultNamespaceMap[$name])) { $_url = $_this->defaultNamespaceMap[$name]; $name = $url; $url = $_url; } return array($name => $url); } /** * Alias to Xml::addNs * * @access public * @static */ function addGlobalNamespace($name, $url = null) { return Xml::addGlobalNs($name, $url); } /** * Removes a namespace added in addNs() * * @param string $name The namespace name or URI * @access public * @static */ function removeGlobalNs($name) { $_this =& XmlManager::getInstance(); if (isset($_this->namespaces[$name])) { unset($_this->namespaces[$name]); unset($this->namespaces[$name]); return true; } elseif (in_array($name, $_this->namespaces)) { $keys = array_keys($_this->namespaces); $count = count($keys); for ($i = 0; $i < $count; $i++) { if ($_this->namespaces[$keys[$i]] == $name) { unset($_this->namespaces[$keys[$i]]); unset($this->namespaces[$keys[$i]]); return true; } } } return false; } /** * Alias to Xml::removeNs * * @access public * @static */ function removeGlobalNamespace($name) { return Xml::removeGlobalNs($name); } /** * Sets/gets global XML options * * @param array $options * @return array * @access public * @static */ function options($options = array()) { $_this =& XmlManager::getInstance(); $_this->options = array_merge($_this->options, $options); return $_this->options; } } /** * The XML Element * */ class XmlElement extends XmlNode { /** * Construct an Xml element * * @param string $name name of the node * @param string $value value of the node * @param array $attributes * @param string $namespace * @return string A copy of $data in XML format */ function __construct($name = null, $value = null, $attributes = array(), $namespace = false) { parent::__construct($name, $value, $namespace); $this->addAttribute($attributes); } /** * Get all the attributes for this element * * @return array */ function attributes() { return $this->attributes; } /** * Add attributes to this element * * @param string $name name of the node * @param string $value value of the node * @return boolean */ function addAttribute($name, $val = null) { if (is_object($name)) { $name = get_object_vars($name); } if (is_array($name)) { foreach ($name as $key => $val) { $this->addAttribute($key, $val); } return true; } if (is_numeric($name)) { $name = $val; $val = null; } if (!empty($name)) { if (strpos($name, 'xmlns') === 0) { if ($name == 'xmlns') { $this->namespace = $val; } else { list($pre, $prefix) = explode(':', $name); $this->addNamespace($prefix, $val); return true; } } $this->attributes[$name] = $val; return true; } return false; } /** * Remove attributes to this element * * @param string $name name of the node * @return boolean */ function removeAttribute($attr) { if (array_key_exists($attr, $this->attributes)) { unset($this->attributes[$attr]); return true; } return false; } } /** * XML text or CDATA node * * Stores XML text data according to the encoding of the parent document * * @package cake * @subpackage cake.cake.libs * @since CakePHP v .1.2.6000 */ class XmlTextNode extends XmlNode { /** * Harcoded XML node name, represents this object as a text node * * @var string */ var $name = '#text'; /** * The text/data value which this node contains * * @var string */ var $value = null; /** * Construct text node with the given parent object and data * * @param object $parent Parent XmlNode/XmlElement object * @param mixed $value Node value */ function __construct($value = null) { $this->value = $value; } /** * Looks for child nodes in this element * * @return boolean False - not supported */ function hasChildren() { return false; } /** * Append an XML node: XmlTextNode does not support this operation * * @return boolean False - not supported * @todo make convertEntities work without mb support, convert entities to number entities */ function append() { return false; } /** * Return string representation of current text node object. * * @return string String representation * @access public */ function toString($options = array(), $depth = 0) { if (is_int($options)) { $depth = $options; $options = array(); } $defaults = array('cdata' => true, 'whitespace' => false, 'convertEntities' => false); $options = array_merge($defaults, Xml::options(), $options); $val = $this->value; if ($options['convertEntities'] && function_exists('mb_convert_encoding')) { $val = mb_convert_encoding($val,'UTF-8', 'HTML-ENTITIES'); } if ($options['cdata'] === true && !is_numeric($val)) { $val = ''; } if ($options['whitespace']) { return str_repeat("\t", $depth) . $val . "\n"; } return $val; } } /** * Manages application-wide namespaces and XML parsing/generation settings. * Private class, used exclusively within scope of XML class. * * @access private */ class XmlManager { /** * Global XML namespaces. Used in all XML documents processed by this application * * @var array * @access public */ var $namespaces = array(); /** * Global XML document parsing/generation settings. * * @var array * @access public */ var $options = array(); /** * Map of common namespace URIs * * @access private * @var array */ var $defaultNamespaceMap = array( 'dc' => 'http://purl.org/dc/elements/1.1/', // Dublin Core 'dct' => 'http://purl.org/dc/terms/', // Dublin Core Terms 'g' => 'http://base.google.com/ns/1.0', // Google Base 'rc' => 'http://purl.org/rss/1.0/modules/content/', // RSS 1.0 Content Module 'wf' => 'http://wellformedweb.org/CommentAPI/', // Well-Formed Web Comment API 'fb' => 'http://rssnamespace.org/feedburner/ext/1.0', // FeedBurner extensions 'lj' => 'http://www.livejournal.org/rss/lj/1.0/', // Live Journal 'itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd', // iTunes 'xhtml' => 'http://www.w3.org/1999/xhtml', // XHTML, 'atom' => 'http://www.w3.org/2005/Atom' // Atom ); /** * Returns a reference to the global XML object that manages app-wide XML settings * * @return object * @access public */ function &getInstance() { static $instance = array(); if (!$instance) { $instance[0] =& new XmlManager(); } return $instance[0]; } }