/** * check, whether string is valid XML name * * <p>XML names are used for tagname, attribute names and various * other, lesser known entities.</p> * <p>An XML name may only consist of alphanumeric characters, * dashes, undescores and periods, and has to start with a letter * or an underscore.</p> * * <code> * require_once 'XML/Util.php'; * * // verify tag name * $result = Util::isValidName('invalidTag?'); * if (is_a($result, 'PEAR_Error')) { * print 'Invalid XML name: ' . $result->getMessage(); * } * </code> * * @param string $string string that should be checked * * @return mixed true, if string is a valid XML name, PEAR error otherwise * @access public * @static * @todo support for other charsets * @todo PEAR CS - unable to avoid 85-char limit on second preg_match */ public static function isValidName($string) { // check for invalid chars if (!preg_match('/^[[:alpha:]_]$/', $string[0])) { return Util::raiseError('XML names may only start with letter ' . 'or underscore', XML_UTIL_ERROR_INVALID_START); } // check for invalid chars if (!preg_match('/^([[:alpha:]_]([[:alnum:]\\-\\.]*)?:)?[[:alpha:]_]([[:alnum:]\\_\\-\\.]+)?$/', $string)) { return Util::raiseError('XML names may only contain alphanumeric ' . 'chars, period, hyphen, colon and underscores', XML_UTIL_ERROR_INVALID_CHARS); } // XML name is valid return true; }
/** * 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; }