How do I add an XMLElement to an XMLElement?
I want to create some XML dynamically and I wonder how I could add an XMLElement to an XMLElement?
Here's my code:
$table = new SimpleXMLElement("<table></table>");
$tableRow = new SimpleXMLElement("<tr></tr>");
$count = count($this->dataSource->columns);
for ($i = 0; $i < $count; $i++)
{
开发者_JAVA百科 $tableRow->addChild("<th></th>","Hi!")
}
$table->addChild($tableRow); // Not good, but this is what I want to do.
Take a look at this: Add Children with SimpleXML
Example:
<?php
$xml = <<<XML
<books>
<book title="Fahrenheit 451" author="Ray Bradbury"/>
<book title="Stranger in a Strange Land" author="Robert Heinlein"/>
</books>
XML;
$sxe = new SimpleXMLElement($xml);
$new_book = $sxe->addChild('book');
$new_book->addAttribute('title', '1984');
$new_book->addAttribute('author', 'George Orwell');
echo $sxe->asXML();
?>
I haven't found the answer to my question. I've coded a class which inherit from SimpleXmlElement and added a method "addChildElement(XElement $element)". The method take an XElement in parameter and add it (and its childs) recursively. I don't know if this is the best way to do it but it seems to work pretty well for me. Tell me if something is wrong with this function. Note that you can't modify an XElement after you've added it to the xml, but I'm working on it.
class XElement extends SimpleXMLElement
{
/**
* Add an XElement to an XElement.
* @param XElement $element
* @return void
*/
public function addChildElement(XElement $element)
{
// TODO Handle namespaces
$addedElement = $this->addChild($element->getName(), (string)$element);
foreach ($element->children() as $node)
{
$addedElement->addChildElement($node);
}
}
}
How to use:
$tableRow = new XElement("<tr></tr>");
$asd = new XElement("<tr2></tr2>");
$asd2 = new XElement("<tr3></tr3>");
$asd->addChildElement($asd2);
$tableRow->addChildElement($asd);
This wont work, but I'm working on it:
$tableRow = new XElement("<tr></tr>");
$asd = new XElement("<tr2></tr2>");
$asd2 = new XElement("<tr3></tr3>");
$tableRow->addChildElement($asd);
$asd->addChildElement($asd2);
Expanding off of the accepted answer I created a static method for more of a XElement from C# feel. It also copied attributes when adding the child XElement node.
class XElement extends SimpleXMLElement
{
/**
* Add an XElement to an XElement.
*
* @param XElement $element A SimpleXmlElement
*
* @return void
*/
public function add(XElement $element)
{
// TODO Handle namespaces
$addedElement = $this->addChild($element->getName(), (string)$element);
$this->_copyAttributes($element, $addedElement);
foreach ($element->children() as $node) {
$addedElement->add($node);
}
}
private function _copyAttributes($from, $to)
{
foreach ($from->attributes() as $n => $v) {
$to->addAttribute($n, $v);
}
}
public static function Node(string $name, $content, $attributes = null)
{
$content_type = gettype($content);
$element = null;
if ($content_type == 'string') {
$element = new XElement("<$name />");
$element[0] = $content;
} else {
if (substr($name, 0, 1) === "<") {
$element = new XElement($name);
} else {
$element = new XElement("<$name />");
}
if ($content_type == 'object' && get_class($content) == 'XElement') {
$element->add($content);
} else if ($content_type == 'array') {
foreach ($content as $c) {
$element->add($c);
}
}
}
if (!empty($attributes)) {
foreach ($attributes as $n => $v) {
$element->addAttribute($n, $v);
}
}
return $element;
}
}
To use:
//auto close tags, add content text
$xml = XElement::Node('cXML', 'nothing');
//nested elements
$xml = XElement::Node('cXML',
XElement::Node('Header',
XElement::Node('Data', 'Your Text Here')
)
);
//attributes
$xml = XElement::Node('cXML',
XElement::Node('Header', '', ['type' => 'no_data'])
);
//multiple nodes (sibling nodes)
$header = XElement::Node('Header', '', ['type' => 'no_data']);
$request = XElement::Node('Request',
XElement::Node('Order',
//inline array
[
XElement::Node('Item',
XElement::Node('Qty', '1')
),
XElement::Node('Item',
XElement::Node('Qty', '2')
),
]
),
['type' => 'data']
);
$nodes = [ $header, $request ];
$xml = XElement::Node('cXML', $nodes);
Output:
<!-- auto close tags, add content text -->
<?xml version="1.0"?>
<cXML>nothing</cXML>
<!-- nested elements -->
<?xml version="1.0"?>
<cXML>
<Header>
<Data>Your Text Here</Data>
</Header>
</cXML>
<!-- attributes -->
<?xml version="1.0"?>
<cXML>
<Header type="no_data"/>
</cXML>
<!-- multiple nodes (sibling nodes) -->
<?xml version="1.0"?>
<cXML>
<Header type="no_data"/>
<Request type="data">
<Order>
<Item>
<Qty>1</Qty>
</Item>
<Item>
<Qty>2</Qty>
</Item>
</Order>
</Request>
</cXML>
精彩评论