/** * create a tag from an array * this method awaits an array in the following format * <pre> * array( * // qualified name of the tag * 'qname' => $qname * * // namespace prefix (optional, if qname is specified or no namespace) * 'namespace' => $namespace * * // local part of the tagname (optional, if qname is specified) * 'localpart' => $localpart, * * // array containing all attributes (optional) * 'attributes' => array(), * * // tag content (optional) * 'content' => $content, * * // namespaceUri for the given namespace (optional) * 'namespaceUri' => $namespaceUri * ) * </pre> * * <code> * require_once 'XML/Util.php'; * * $tag = array( * 'qname' => 'foo:bar', * 'namespaceUri' => 'http://foo.com', * 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), * 'content' => 'I\'m inside the tag', * ); * // creating a tag with qualified name and namespaceUri * $string = Util::createTagFromArray($tag); * </code> * * @param array $tag tag definition * @param int $replaceEntities whether to replace XML special chars in * content, embedd it in a CData section * or none of both * @param bool $multiline whether to create a multiline tag where each * attribute gets written to a single line * @param string $indent string used to indent attributes * (_auto indents attributes so they start * at the same column) * @param string $linebreak string used for linebreaks * @param bool $sortAttributes Whether to sort the attributes or not * * @return string XML tag * @access public * @static * @see createTag() * @uses attributesToString() to serialize the attributes of the tag * @uses splitQualifiedName() to get local part and namespace of a qualified name * @uses createCDataSection() * @uses raiseError() */ public static function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = '_auto', $linebreak = "\n", $sortAttributes = true) { if (isset($tag['content']) && !is_scalar($tag['content'])) { return Util::raiseError('Supplied non-scalar value as tag content', XML_UTIL_ERROR_NON_SCALAR_CONTENT); } if (!isset($tag['qname']) && !isset($tag['localPart'])) { return Util::raiseError('You must either supply a qualified name ' . '(qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME); } // if no attributes hav been set, use empty attributes if (!isset($tag['attributes']) || !is_array($tag['attributes'])) { $tag['attributes'] = array(); } if (isset($tag['namespaces'])) { foreach ($tag['namespaces'] as $ns => $uri) { $tag['attributes']['xmlns:' . $ns] = $uri; } } if (!isset($tag['qname'])) { // qualified name is not given // check for namespace if (isset($tag['namespace']) && !empty($tag['namespace'])) { $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart']; } else { $tag['qname'] = $tag['localPart']; } } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) { // namespace URI is set, but no namespace $parts = Util::splitQualifiedName($tag['qname']); $tag['localPart'] = $parts['localPart']; if (isset($parts['namespace'])) { $tag['namespace'] = $parts['namespace']; } } if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) { // is a namespace given if (isset($tag['namespace']) && !empty($tag['namespace'])) { $tag['attributes']['xmlns:' . $tag['namespace']] = $tag['namespaceUri']; } else { // define this Uri as the default namespace $tag['attributes']['xmlns'] = $tag['namespaceUri']; } } // check for multiline attributes if ($multiline === true) { if ($indent === '_auto') { $indent = str_repeat(' ', strlen($tag['qname']) + 2); } } // create attribute list $attList = Util::attributesToString($tag['attributes'], $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities); if (!isset($tag['content']) || (string) $tag['content'] == '') { $tag = sprintf('<%s%s />', $tag['qname'], $attList); } else { switch ($replaceEntities) { case XML_UTIL_ENTITIES_NONE: break; case XML_UTIL_CDATA_SECTION: $tag['content'] = Util::createCDataSection($tag['content']); break; default: $tag['content'] = Util::replaceEntities($tag['content'], $replaceEntities); break; } $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'], $tag['qname']); } return $tag; }
/** * create a tag from an array * this method awaits an array in the following format * array( * 'qname' => $tagName, * 'attributes' => array(), * 'content' => $content, // optional * 'namespace' => $namespace // optional * 'namespaceUri' => $namespaceUri // optional * ) * * @param array $tag tag definition * @param boolean $firstCall whether or not this is the first call * * @return string $string XML tag * @access private */ function _createXMLTag($tag, $firstCall = true) { // build fully qualified tag name if ($this->options[XML_SERIALIZER_OPTION_NAMESPACE] !== null) { if (is_array($this->options[XML_SERIALIZER_OPTION_NAMESPACE])) { $tag['qname'] = $this->options[XML_SERIALIZER_OPTION_NAMESPACE][0] . ':' . $tag['qname']; } else { $tag['qname'] = $this->options[XML_SERIALIZER_OPTION_NAMESPACE] . ':' . $tag['qname']; } } // attribute indentation if ($this->options[XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES] !== false) { $multiline = true; $indent = str_repeat($this->options[XML_SERIALIZER_OPTION_INDENT], $this->_tagDepth); if ($this->options[XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES] == '_auto') { $indent .= str_repeat(' ', strlen($tag['qname']) + 2); } else { $indent .= $this->options[XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES]; } } else { $multiline = false; $indent = false; } if (is_array($tag['content'])) { if (empty($tag['content'])) { $tag['content'] = ''; } } elseif (XML_SERIALIZER_OPTION_FALSE_AS_STRING && $tag['content'] === false) { $tag['content'] = '0'; } elseif (is_scalar($tag['content']) && (string) $tag['content'] == '') { $tag['content'] = ''; } // replace XML entities if ($firstCall === true) { if ($this->options[XML_SERIALIZER_OPTION_CDATA_SECTIONS] === true) { $replaceEntities = XML_UTIL_CDATA_SECTION; } else { $replaceEntities = $this->options[XML_SERIALIZER_OPTION_ENTITIES]; } } else { // this is a nested call, so value is already encoded // and must not be encoded again $replaceEntities = XML_SERIALIZER_ENTITIES_NONE; // but attributes need to be encoded anyways // (done here because the rest of the code assumes the same encoding // can be used both for attributes and content) foreach ($tag['attributes'] as $k => $v) { $v = Util::replaceEntities($v, $this->options[XML_SERIALIZER_OPTION_ENTITIES]); $tag['attributes'][$k] = $v; } } if (is_scalar($tag['content']) || is_null($tag['content'])) { if ($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC]) { if ($firstCall === true) { $tag['content'] = call_user_func($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['content']); } $tag['attributes'] = array_map($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['attributes']); } $tag = Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options[XML_SERIALIZER_OPTION_LINEBREAKS]); } elseif (is_array($tag['content'])) { $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']); } elseif (is_object($tag['content'])) { $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']); } elseif (is_resource($tag['content'])) { settype($tag['content'], 'string'); if ($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC]) { if ($replaceEntities === true) { $tag['content'] = call_user_func($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['content']); } $tag['attributes'] = array_map($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['attributes']); } $tag = Util::createTagFromArray($tag, $replaceEntities); } return $tag; }