9

SimpleXMLElement オブジェクト $child と SimpleXMLElement オブジェクト $parent があります。

$child を $parent の子として追加するにはどうすればよいですか? DOM に変換せずにこれを行う方法はありますか?

addChild() メソッドは、新しい空の要素を作成することしかできないようですが、 $child を追加したい要素に子もある場合は役に立ちません。ここで再帰が必要かもしれないと思っています。

4

4 に答える 4

10

残念ながらSimpleXMLElement、2 つの要素を一緒にするものは何も提供していません。@nickf が書いたように、操作よりも読み取りに適しています。ただし、姉妹拡張機能DOMDocumentは編集用であり、 を介して両方をまとめることができますdom_import_simplexml()。@salatheは、関連する回答で、これが特定の SimpleXMLElements に対してどのように機能するかを示しています。

以下は、これが入力チェックとその他のオプションでどのように機能するかを示しています。2つの例でそれを行います。最初の例は、XML 文字列を挿入する関数です。

/**
 * Insert XML into a SimpleXMLElement
 *
 * @param SimpleXMLElement $parent
 * @param string $xml
 * @param bool $before
 * @return bool XML string added
 */
function simplexml_import_xml(SimpleXMLElement $parent, $xml, $before = false)
{
    $xml = (string)$xml;

    // check if there is something to add
    if ($nodata = !strlen($xml) or $parent[0] == NULL) {
        return $nodata;
    }

    // add the XML
    $node     = dom_import_simplexml($parent);
    $fragment = $node->ownerDocument->createDocumentFragment();
    $fragment->appendXML($xml);

    if ($before) {
        return (bool)$node->parentNode->insertBefore($fragment, $node);
    }

    return (bool)$node->appendChild($fragment);
}

この例示的な関数により、XML を追加したり、ルート要素を含む特定の要素の前に挿入したりできます。追加するものがあるかどうかを確認した後、DOMDocumentの関数とメソッドを使用して XML をドキュメント フラグメントとして挿入します。これについては、 How to import XML string in a PHP DOMDocument に も記載されています。使用例:

$parent = new SimpleXMLElement('<parent/>');

// insert some XML
simplexml_import_xml($parent, "\n  <test><this>now</this></test>\n");

// insert some XML before a certain element, here the first <test> element
// that was just added
simplexml_import_xml($parent->test, "<!-- leave a comment -->\n  ", $before = true);

// you can place comments above the root element
simplexml_import_xml($parent, "<!-- this works, too -->", $before = true);

// but take care, you can produce invalid XML, too:
// simplexml_add_xml($parent, "<warn><but>take care!</but> you can produce invalid XML, too</warn>", $before = true);

echo $parent->asXML();

これにより、次の出力が得られます。

<?xml version="1.0"?>
<!-- this works, too -->
<parent>
  <!-- leave a comment -->
  <test><this>now</this></test>
</parent>

2 番目の例は、SimpleXMLElement. 必要に応じて、最初の関数を使用します。基本的に、何かすることがあるかどうか、どの種類の要素をインポートするかをチェックします。属性の場合は追加するだけで、要素の場合は XML にシリアル化されてから、XML として親要素に追加されます。

/**
 * Insert SimpleXMLElement into SimpleXMLElement
 *
 * @param SimpleXMLElement $parent
 * @param SimpleXMLElement $child
 * @param bool $before
 * @return bool SimpleXMLElement added
 */
function simplexml_import_simplexml(SimpleXMLElement $parent, SimpleXMLElement $child, $before = false)
{
    // check if there is something to add
    if ($child[0] == NULL) {
        return true;
    }

    // if it is a list of SimpleXMLElements default to the first one
    $child = $child[0];

    // insert attribute
    if ($child->xpath('.') != array($child)) {
        $parent[$child->getName()] = (string)$child;
        return true;
    }

    $xml = $child->asXML();

    // remove the XML declaration on document elements
    if ($child->xpath('/*') == array($child)) {
        $pos = strpos($xml, "\n");
        $xml = substr($xml, $pos + 1);
    }

    return simplexml_import_xml($parent, $xml, $before);
}

この例示的な関数は、Simplexml で一般的な要素と属性のリストを正規化します。一度に複数の SimpleXMLElements を挿入するように変更することもできますが、以下の使用例に示すように、私の例ではそれがサポートされていません (属性の例を参照)。

// append the element itself to itself
simplexml_import_simplexml($parent, $parent);

// insert <this> before the first child element (<test>)
simplexml_import_simplexml($parent->children(), $parent->test->this, true);

// add an attribute to the document element
$test = new SimpleXMLElement('<test attribute="value" />');
simplexml_import_simplexml($parent, $test->attributes());

echo $parent->asXML();

これは最初の使用例の続きです。したがって、出力は次のようになります。

<?xml version="1.0"?>
<!-- this works, too -->
<parent attribute="value">
  <!-- leave a comment -->
  <this>now</this><test><this>now</this></test>
<!-- this works, too -->
<parent>
  <!-- leave a comment -->
  <test><this>now</this></test>
</parent>
</parent>

これがお役に立てば幸いです。コードは Gistオンライン デモ/ PHP バージョン概要にあります。

于 2013-02-12T11:24:23.190 に答える
6

これが最も役立つ答えではないことはわかっていますが、特に XML を作成/変更しているので、DOM 関数の使用に切り替えます。SimpleXML は単純なドキュメントへのアクセスには適していますが、それらを変更するのはかなり苦手です。

dom_import_simplexml()SimpleXML が他のすべての場所で親切に扱ってくれて、それを使い続けたい場合は、必要なことを実行するために一時的に DOM 関数にジャンプしてから、 andを使用して再びジャンプするオプションがまだありますsimplexml_import_dom()。これがどれほど効率的かはわかりませんが、役立つかもしれません。

于 2009-04-20T08:16:49.040 に答える
-2

addChild()実際、 がどのように定義されているかを注意深く調べれば、(動的に) 可能です。この手法を使用して、再帰と参照渡しを使用して任意の配列を XML に変換しました。

  • addChild()SimpleXMLElement追加された子の返品。
  • リーフ ノードを追加するには、 を使用します$xml->addChilde($nodeName, $nodeValue)
  • サブノードまたは値を持つノードを追加するには、 を使用 します。$xml->addChilde($nodeName)には値が渡されませんaddChild()。これにより、SimpleXMLElement 型のサブノードが作成されます。文字列ではありません!

ターゲット XML

<root>
    <node>xyz</node>
    <node>
        <node>aaa</node>
        <node>bbb</node>
    </node>
</root>

コード:

$root = new SimpleXMLElement('<root />');
//add child with name and string value.
$root.addChild('node', 'xyz'); 
//adds child with name as root of new SimpleXMLElement
$sub = $root->addChild('node');
$sub.addChild('node', 'aaa');
$sub.addChild('node', 'bbb');
于 2013-01-16T16:32:11.903 に答える
-3

このページを偶然見つけたので、これをここに残しておくと、SimpleXMLが::addChildメソッドを介してこの機能をサポートするようになりました。

このメソッドを使用して、カスケード要素を追加することもできます。

$xml->addChild('parent');
$xml->parent->addChild('child');
$xml->parent->child->addChild('child_id','12345');
于 2012-06-11T23:15:45.177 に答える