src/XML/Util.php
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 XML_Util::raiseError('Supplied non-scalar value as tag content',
            XML_UTIL_ERROR_NON_SCALAR_CONTENT);
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_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 = XML_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 = XML_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'] = XML_Util::createCDataSection($tag['content']);
                break;
            default:
                $tag['content'] = XML_Util::replaceEntities($tag['content'], 
                    $replaceEntities);
                break;
            }
            $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
                $tag['qname']);
        }
        return $tag;
    }
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 XML_Util::raiseError('Supplied non-scalar value as tag content',
            XML_UTIL_ERROR_NON_SCALAR_CONTENT);
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_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 = XML_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 = XML_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'] = XML_Util::createCDataSection($tag['content']);
                break;
            default:
                $tag['content'] = XML_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
<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 = XML_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()