Recursive creation of XML

@param string       $element The child's name
@param string|array $data    Element value

@return \DOMElement

@throws InvalidArgumentException
975214
protected function processGenerate($element, $data)
    {
        $this->prepareElementName($element);

        /** setRootName(null) support */
        if('' === (string) $element)
        {
            $element = array_keys($data)[0];

            return $this->processGenerate($element, $data[$element]);
        }

        /** @var \DOMElement $node */
        $node = $this->getDomDocument()->createElement($element);

        if(is_array($data))
        {
            $this->applyAttributes($data, $node);

            if(isset($data['@value']))
            {
                $this->applyValue($data, $node);

                return $node;
            }
            elseif(isset($data['@cdata']))
            {
                $this->applyCData($data, $node);

                return $node;
            }
            elseif(isset($data['@ns']))
            {
                $this->applyNamespace($data, $node);
            }
        }

        if(is_array($data))
        {
            foreach($data as $key => $value)
            {
                $this->prepareElementName($key);

                if('' === $key || false === $this->isValidElementName($key))
                {
                    continue;
                }

                if(is_array($value) && is_numeric(key($value)))
                {
                    foreach($value as $k => $v)
                    {
                        $node->appendChild($this->processGenerate($key, $v));
                    }
                }
                else
                {
                    $node->appendChild($this->processGenerate($key, $value));
                }

                unset($data[$key]);
            }
        }

        if(!is_array($data))
        {
            $data = $this->getBooleanAsString($data);

            $node->appendChild(
                $this->getDomDocument()->createTextNode($data)
            );
        }

        return $node;
    }
723228
public function getContentForElement(Element $element) : string
    {
        if ($element instanceof HasChildren && $element instanceof HasContent) {
            throw new InvalidArgumentException('An element can only implement one of HasChildren and HasContent');
        }

        if ($element instanceof HasChildren) {
            $renderedChildren = array_map(function(Element $element) {
                return $this->renderElement($element);
            }, $element->getChildren());

            return implode('', $renderedChildren);
        }

        if ($element instanceof HasContent) {
            return $element->getContent();
        }

        return '';
    }
893704
public static function create( $name, $content = NULL, $attributes = array(), $data = array() )
	{
		if( !strlen( $name	= trim( $name ) ) )
			throw new InvalidArgumentException( 'Missing tag name' );
		$name		= strtolower( $name );
		try{
			$attributes	= self::renderAttributes( $attributes );
			$data		= self::renderData( $data );
		}
		catch( InvalidArgumentException $e ) {
			if( version_compare( PHP_VERSION, '5.3.0', '>=' ) )
				throw new RuntimeException( 'Invalid attributes', NULL, $e );						//  throw exception and transport inner exception
			throw new RuntimeException( 'Invalid attributes', NULL );								//  throw exception
		}
		if( $content === NULL || $content === FALSE )												//  no node content defined, not even an empty string
			if( !in_array( $name, self::$shortTagExcludes ) )										//  node name is allowed to be a short tag
				return "<".$name.$attributes.$data."/>";											//  build and return short tag
		if( is_array( $content ) )																	//  content is an array, may be nested
			$content	= self::flattenArray( $content, '' );
		if( is_numeric( $content ) )
			$content	= (string) $content;
		if( is_object( $content ) ){
			if( !method_exists( $content, '__toString' ) ){											//  content is not a renderable object
				$message	= 'Object of class "'.get_class( $content ).'" cannot be rendered';		//  prepare message about not renderable object
				throw new InvalidArgumentException( $message ); 									//  break with error message
			}
			$content	= (string) $content;														//  render object to string
		}
		if( !is_null( $content ) && !is_string( $content ) ){										//  content is neither NULL nor string so far
			$message	= 'Content type "'.gettype( $content ).'" is not supported';				//  prepare message about wrong content data type
			throw new InvalidArgumentException( $message ); 										//  break with error message
		}
		return "<".$name.$attributes.$data.">".$content."</".$name.">";								//  build and return full tag
	}
471282
protected function reparentElement(DOMElement $element)
	{
		$parentNode = $element->parentNode;
		do
		{
			$lastChild = $parentNode->lastChild;
			$parentNode->parentNode->insertBefore($lastChild, $parentNode->nextSibling);
		}
		while (!$lastChild->isSameNode($element));
	}
480409
protected function buildXML(DOMDocument $dom, \DOMNode $node, $data)
    {
        $normalizer = $this->getNormalizer();

        if (null === $data) {
            return;
        }

        if ((is_array($data) || $data instanceof \Traversable) && !$this->isXmlElement($data)) {
            return $this->buildXmlFromTraversable($dom, $node, $normalizer->ensureBuildable($data));
        }

        $this->setElementValue($dom, $node, $data);
    }
636314
protected static function arrayToXML($data, &$xml = null){

            if($xml === null)
                $xml = new \SimpleXMLElement("<?xml version=\"1.0\"?><nondb></nondb>");
            foreach($data as $k=>$v){
                if(is_array($v)){
                    $sub = $xml->addChild("$k");
                    self::arrayToXML($v, $sub);
                }else{
                    $xml->addChild("$k", htmlspecialchars("$v"));
                }
            }

            return $xml->asXML();

        }
75720
protected static function loopEncode($data, $domElement)
    {
        if (is_array($data)) {
            foreach ($data as $index => $mixedElement) {
                if (is_int($index)) {
                    if ($index == 0) {
                        $node = $domElement;
                    } else {
                        $node = new DOMElement($domElement->tagName);
                        $domElement->parentNode->appendChild($node);
                    }
                } else {
                    $node = new DOMElement($index);
                    $domElement->appendChild($node);
                }
                 
                self::loopEncode($mixedElement, $node);
            }
        } else {
            $domElement->appendChild(new DOMText($data));
        }

        return $domElement;
    }
1022296
public function addCustomElement($element)
    {
        if (($colon = strpos($element, ':')) !== false) {
            $namespace = substr($element, 0, $colon);
            if (!$this->hasNamespace($namespace)) {
                throw new \InvalidArgumentException(sprintf('Unregistered namespace: %s', $namespace));
            }
        }

        $this->customElements[] = $element;

        return $this;
    }
1188813
public function prepend(DOMElement &$parent, &$child)
    {
        if (empty($child)) {
            throw new InvalidArgumentException('You are trying to prepend an empty element.');
        }

        // Append before first child
        if ($parent->childNodes->length > 0) {
            $parent->insertBefore($child, $parent->childNodes->item(0));
        } else {
            $this->append($parent, $child);
        }

        // Return the DOMElement
        return $parent;
    }
1268297
public static function arrayToXml(\DOMDocument $xml, \DOMNode $node, $array = [])
    {
        foreach ($array as $el => $val) {
            if (is_array($val)) {
                self::arrayToXml($xml, $node->$el, $val);
            } else {
                $node->appendChild($xml->createElement($el, $val));
            }
        }
        return $xml;
    }
1262142
public function append(DOMElement &$parent, &$child)
    {
        // Check element
        if (empty($child)) {
            throw new InvalidArgumentException('You are trying to append an empty element.');
        }

        // Append element
        $parent->appendChild($child);

        // Return the DOMElement
        return $parent;
    }
853336
public function inject(Xml $element)
	{
		$element->setAncestor($this->getAncestor());
		$element->setRoot($this->getRoot());
		$element->parent = $this;
		return $this->appendChild($element);
	}
1200462
public function updateElement(Element $element, array $data) {
        if (isset($data["id"])) {
            $element->setId($data["id"]);
        }
        if (isset($data["class"])) {
            $element->addClass($data["class"]);
        }
        return $element;
    }
594541
private function buildXml(\DOMNode $parentNode, $data, string $xmlRootNodeName = null): bool
    {
        $append = true;
        $removeEmptyTags = $this->context[self::REMOVE_EMPTY_TAGS] ?? $this->defaultContext[self::REMOVE_EMPTY_TAGS] ?? false;
        $encoderIgnoredNodeTypes = $this->context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES];

        if (\is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) {
            foreach ($data as $key => $data) {
                //Ah this is the magic @ attribute types.
                if (0 === strpos($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) {
                    if (!is_scalar($data)) {
                        $data = $this->serializer->normalize($data, $this->format, $this->context);
                    }
                    $parentNode->setAttribute($attributeName, $data);
                } elseif ('#' === $key) {
                    $append = $this->selectNodeType($parentNode, $data);
                } elseif ('#comment' === $key) {
                    if (!\in_array(XML_COMMENT_NODE, $encoderIgnoredNodeTypes, true)) {
                        $append = $this->appendComment($parentNode, $data);
                    }
                } elseif (\is_array($data) && false === is_numeric($key)) {
                    // Is this array fully numeric keys?
                    if (ctype_digit(implode('', array_keys($data)))) {
                        /*
                         * Create nodes to append to $parentNode based on the $key of this array
                         * Produces <xml><item>0</item><item>1</item></xml>
                         * From ["item" => [0,1]];.
                         */
                        foreach ($data as $subData) {
                            $append = $this->appendNode($parentNode, $subData, $key);
                        }
                    } else {
                        $append = $this->appendNode($parentNode, $data, $key);
                    }
                } elseif (is_numeric($key) || !$this->isElementNameValid($key)) {
                    $append = $this->appendNode($parentNode, $data, 'item', $key);
                } elseif (null !== $data || !$removeEmptyTags) {
                    $append = $this->appendNode($parentNode, $data, $key);
                }
            }

            return $append;
        }

        if (\is_object($data)) {
            $data = $this->serializer->normalize($data, $this->format, $this->context);
            if (null !== $data && !is_scalar($data)) {
                return $this->buildXml($parentNode, $data, $xmlRootNodeName);
            }

            // top level data object was normalized into a scalar
            if (!$parentNode->parentNode->parentNode) {
                $root = $parentNode->parentNode;
                $root->removeChild($parentNode);

                return $this->appendNode($root, $data, $xmlRootNodeName);
            }

            return $this->appendNode($parentNode, $data, 'data');
        }

        throw new NotEncodableValueException(sprintf('An unexpected value could not be serialized: %s', var_export($data, true)));
    }
1174384
public function setData($data)
    {
        if (!$data instanceof \SimpleXMLElement) {
            throw new \InvalidArgumentException(__METHOD__ . ' argument should be instance of ' . \SimpleXMLElement::class);
        }

        $this->data = $data;

        return $this;
    }
753386
protected function toString($data)
    {
        if ($data instanceof \SimpleXMLElement) {
            return $data->asXML();
        } elseif ($data instanceof \DOMDocument) {
            return $data->saveXML();
        } elseif (is_string($data)) {
            return $data;
        }

        throw new \InvalidArgumentException(
            sprintf(
                'Invalid XML content type, %s provided.',
                gettype($data)
            )
        );
    }
272592
protected function addElement($element)
    {
        if($element->getData() == null) {
            throw new Exception("Invalid Element data: null is not allowed.");
        }
        if ($this->elementExistsWith($element->getData())) {
            $this->addWeightToExisting($element);
        } else {
            $this->elements[] = $element;
        }

        return $this;
    }