_content = array(); $this->_pushContent_array(func_get_args()); } function pushContent ($arg /*, ...*/) { if (func_num_args() > 1) $this->_pushContent_array(func_get_args()); elseif (is_array($arg)) $this->_pushContent_array($arg); else $this->_pushContent($arg); } function _pushContent_array ($array) { foreach ($array as $item) { if (is_array($item)) $this->_pushContent_array($item); else $this->_pushContent($item); } } function _pushContent ($item) { if (get_class($item) == 'xmlcontent') array_splice($this->_content, count($this->_content), 0, $item->_content); else $this->_content[] = $item; } function unshiftContent ($arg /*, ...*/) { if (func_num_args() > 1) $this->_unshiftContent_array(func_get_args()); elseif (is_array($arg)) $this->_unshiftContent_array($arg); else $this->_unshiftContent($arg); } function _unshiftContent_array ($array) { foreach (array_reverse($array) as $item) { if (is_array($item)) $this->_unshiftContent_array($item); else $this->_unshiftContent($item); } } function _unshiftContent ($item) { if (get_class($item) == 'xmlcontent') array_splice($this->_content, 0, 0, $item->_content); else array_unshift($this->_content, $item); } function getContent () { return $this->_content; } function setContent ($arg /* , ... */) { $this->_content = array(); $this->_pushContent_array(func_get_args()); } function printXML () { foreach ($this->_content as $item) { if (is_object($item)) { if (method_exists($item, 'printxml')) $item->printXML(); elseif (method_exists($item, 'asxml')) echo $item->asXML(); elseif (method_exists($item, 'asstring')) echo $this->_quote($item->asString()); else printf("==Object(%s)==", get_class($item)); } else echo $this->_quote((string) $item); } } function asXML () { $xml = ''; foreach ($this->_content as $item) { if (is_object($item)) { if (method_exists($item, 'asxml')) $xml .= $item->asXML(); elseif (method_exists($item, 'asstring')) $xml .= $this->_quote($item->asString()); else $xml .= sprintf("==Object(%s)==", get_class($item)); } else $xml .= $this->_quote((string) $item); } return $xml; } function asString () { $val = ''; foreach ($this->_content as $item) { if (is_object($item)) { if (method_exists($item, 'asstring')) $val .= $item->asString(); else $val .= sprintf("==Object(%s)==", get_class($item)); } else $val .= (string) $item; } return trim($val); } /** * See if element is empty. * * Empty means it has no content. * @return bool True if empty. */ function isEmpty () { if (empty($this->_content)) return true; foreach ($this->_content as $x) { if (!empty($x)) return false; } return true; } function _quote ($string) { return str_replace('<', '<', str_replace('>', '>', str_replace('&', '&', $string))); } }; /** * An XML element. * * @param $tagname string Tag of html element. */ class XmlElement extends XmlContent { function XmlElement ($tagname /* , $attr_or_content , ...*/) { $this->XmlContent(); $this->_init(func_get_args()); } function _init ($args) { if (!is_array($args)) $args = func_get_args(); assert(count($args) >= 1); //assert(is_string($args[0])); $this->_tag = array_shift($args); if ($args && is_array($args[0])) $this->_attr = array_shift($args); else { $this->_attr = array(); if ($args && $args[0] === false) array_shift($args); } $this->setContent($args); } function getTag () { return $this->_tag; } function setAttr ($attr, $value = false) { if (is_array($attr)) { assert($value === false); foreach ($attr as $a => $v) $this->set($a, $v); return; } assert(is_string($attr)); if ($value === false) { unset($this->_attr[$attr]); } if (is_bool($value)) $value = $attr; $this->_attr[$attr] = (string) $value; } function getAttr ($attr) { if (isset($this->_attr[$attr])) return $this->_attr[$attr]; else return false; } function startTag() { $start = "<" . $this->_tag; foreach ($this->_attr as $attr => $val) { if (is_bool($val)) { if (!$val) continue; $val = $attr; } $qval = str_replace("\"", '"', $this->_quote($val)); $start .= " $attr=\"$qval\""; } $start .= ">"; return $start; } function emptyTag() { return substr($this->startTag(), 0, -1) . "/>"; } function endTag() { return "_tag>"; } function printXML () { if ($this->isEmpty()) echo $this->emptyTag(); else { echo $this->startTag(); // FIXME: The next two lines could be removed for efficiency if (!$this->hasInlineContent()) echo "\n"; XmlContent::printXML(); echo "_tag>"; if (!$this->isInlineElement()) echo "\n"; } } function asXML () { if ($this->isEmpty()) return $this->emptyTag(); else { $xml = $this->startTag(); // FIXME: The next two lines could be removed for efficiency if (!$this->hasInlineContent()) $xml .= "\n"; $xml .= XmlContent::asXML(); $xml .= "_tag>"; if (!$this->isInlineElement()) $xml .= "\n"; return $xml; } } /** * Can this element have inline content? * * This is a hack, but is probably the best one can do without * knowledge of the DTD... */ function hasInlineContent () { // This is a hack. if (empty($this->_content)) return true; if (is_object($this->_content[0])) return false; return true; } /** * Is this element part of inline content? * * This is a hack, but is probably the best one can do without * knowledge of the DTD... */ function isInlineElement () { return false; } }; class RawXml { function RawXml ($xml_text) { $this->_xml = $xml_text; } function printXML () { echo $this->_xml; } function asXML () { return $this->_xml; } function isEmpty () { return empty($this->_xml); } } class FormattedText { function FormattedText ($fs /* , ... */) { if ($fs !== false) { $this->_init(func_get_args()); } } function _init ($args) { $this->_fs = array_shift($args); // PHP's sprintf doesn't support variable width specifiers, // like sprintf("%*s", 10, "x"); --- so we won't either. if (! preg_match_all('/(?_fs, $m)) { $this->_args = $args; } else { // Format string has '%2$s' style argument reordering. // PHP doesn't support this. if (preg_match('/(?_fs = preg_replace('/(?_fs); $this->_args = array(); foreach($m[1] as $argnum) { if ($argnum < 1 || $argnum > count($args)) trigger_error(sprintf("%s: argument index out of range", $argnum), E_USER_WARNING); $this->_args[] = $args[$argnum - 1]; } } } function asXML () { // Not all PHP's have vsprintf, so... $args[] = XmlElement::_quote($this->_fs); foreach ($this->_args as $arg) $args[] = AsXML($arg); return call_user_func_array('sprintf', $args); } function printXML () { // Not all PHP's have vsprintf, so... $args[] = XmlElement::_quote($this->_fs); foreach ($this->_args as $arg) $args[] = AsXML($arg); call_user_func_array('printf', $args); } function asString() { $args[] = $this->_fs; foreach ($this->_args as $arg) $args[] = AsString($arg); return call_user_func_array('sprintf', $args); } } function PrintXML ($val /* , ... */ ) { if (func_num_args() > 1) { foreach (func_get_args() as $arg) PrintXML($arg); } elseif (is_object($val)) { if (method_exists($val, 'printxml')) $val->printXML(); elseif (method_exists($val, 'asxml')) { echo $val->asXML(); } elseif (method_exists($val, 'asstring')) echo XmlContent::_quote($val->asString()); else printf("==Object(%s)==", get_class($val)); } elseif (is_array($val)) { // DEPRECATED: // Use XmlContent objects instead of arrays for collections of XmlElements. trigger_error("Passing arrays to PrintXML() is deprecated: (" . AsXML($val, true) . ")", E_USER_NOTICE); foreach ($val as $x) PrintXML($x); } else echo (string)XmlContent::_quote($val); } function AsXML ($val /* , ... */) { static $nowarn; if (func_num_args() > 1) { $xml = ''; foreach (func_get_args() as $arg) $xml .= AsXML($arg); return $xml; } elseif (is_object($val)) { if (method_exists($val, 'asxml')) return $val->asXML(); elseif (method_exists($val, 'asstring')) return XmlContent::_quote($val->asString()); else return sprintf("==Object(%s)==", get_class($val)); } elseif (is_array($val)) { // DEPRECATED: // Use XmlContent objects instead of arrays for collections of XmlElements. if (empty($nowarn)) { $nowarn = true; trigger_error("Passing arrays to AsXML() is deprecated: (" . AsXML($val) . ")", E_USER_NOTICE); unset($nowarn); } $xml = ''; foreach ($val as $x) $xml .= AsXML($x); return $xml; } else return XmlContent::_quote((string)$val); } function AsString ($val) { if (func_num_args() > 1) { $str = ''; foreach (func_get_args() as $arg) $str .= AsString($arg); return $str; } elseif (is_object($val)) { if (method_exists($val, 'asstring')) return $val->asString(); else return sprintf("==Object(%s)==", get_class($val)); } elseif (is_array($val)) { // DEPRECATED: // Use XmlContent objects instead of arrays for collections of XmlElements. trigger_error("Passing arrays to AsString() is deprecated", E_USER_NOTICE); $str = ''; foreach ($val as $x) $str .= AsString($x); return $str; } return (string) $val; } function fmt ($fs /* , ... */) { $s = new FormattedText(false); $args = func_get_args(); $args[0] = _($args[0]); $s->_init($args); return $s; } // (c-file-style: "gnu") // Local Variables: // mode: php // tab-width: 8 // c-basic-offset: 4 // c-hanging-comment-ender-p: nil // indent-tabs-mode: nil // End: ?>