如何将XMLElement添加到XMLElement?

时间:2011-04-16 23:41:49

标签: php xml simplexml

我想动态创建一些XML,我想知道如何将XMLElement添加到XMLElement中?

这是我的代码:

    $table = new SimpleXMLElement("<table></table>");
    $tableRow = new SimpleXMLElement("<tr></tr>");

    $count = count($this->dataSource->columns);
    for ($i = 0; $i < $count; $i++)
    {
        $tableRow->addChild("<th></th>","Hi!") 
    }

    $table->addChild($tableRow); // Not good, but this is what I want to do.

3 个答案:

答案 0 :(得分:1)

看看这个:Add Children with SimpleXML

示例:

<?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();

?>

答案 1 :(得分:0)

我没有找到问题的答案。 我编写了一个继承自SimpleXmlElement的类,并添加了一个方法“addChildElement(XElement $ element)”。该方法在参数中使用XElement并递归地添加它(及其子)。 我不知道这是否是最好的方法,但它似乎对我来说非常好。 告诉我这个功能是否有问题。 请注意,在将XElement添加到xml后,您无法修改它,但我正在处理它。

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);
        }
    }
}

使用方法:

$tableRow = new XElement("<tr></tr>");
$asd = new XElement("<tr2></tr2>");
$asd2 = new XElement("<tr3></tr3>");
$asd->addChildElement($asd2);
$tableRow->addChildElement($asd);

这不会奏效,但我正在努力:

$tableRow = new XElement("<tr></tr>");
$asd = new XElement("<tr2></tr2>");
$asd2 = new XElement("<tr3></tr3>");
$tableRow->addChildElement($asd);
$asd->addChildElement($asd2);

答案 2 :(得分:0)

扩展已接受的答案我为C#感觉更多的XElement创建了一个静态方法。它还在添加子XElement节点时复制了属性。

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;
    }
}

使用:

//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);

输出:

<!-- 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>