Добавить дочерний элемент в xml на основе атрибута родительского узла в php

#php #xml

#php #xml

Вопрос:

Я хотел бы спросить, как легко добавить новый узел в конец найденного узла в php. Допустим, у меня есть xml, подобный этому:

 <Root>
    <child id=1>
        <text>smth</text>
    </child>
</Root>
  

Я хочу найти дочерний элемент с идентификатором 1, а затем добавить другой узел в качестве последнего.
Я пытался найти ответ, но он либо отвечал, как его найти, либо как записать в него, к сожалению, я не смог собрать его вместе.

Я был бы очень рад, если кто-нибудь сможет мне с этим помочь.

Комментарии:

1. Вы пытались написать какой-нибудь код? Даже что-то базовое…

2. Здравствуйте, да, но я всегда заканчиваю тем, что нахожу Элемент, но не знаю, как добавить к нему дочерний элемент. Я пробовал DOMDocument и simplexml_load_file

3. simplexmlelement имеет addChild() метод

4. @JOUM, вы можете проверить ответ, который я только что добавил 🙂

Ответ №1:

Вы можете использовать xpath , чтобы найти соответствующий узел (на основе id ), а затем использовать addChild , чтобы добавить новый дочерний узел к узлу, который вы только что нашли:

 $str =<<< END
<Root>
    <child id="1">
        <text>smth</text>
    </child>
</Root>
END;

$result = simplexml_load_string($str);

$child = $result->xpath("*[@id='1']")[0];
$child->addChild('text', 'node value');

// The part from here is only to make the output pretty-xml
// instead you can just use $result->saveXML()
$dom = new DOMDocument("1.0");
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($result->saveXML());
var_dump($dom->saveXML());
  

Результат будет:

 string(115) "<?xml version="1.0"?>
<Root>
    <child id="1">
        <text>smth</text>
        <text>node value</text>
    </child>
</Root>
"
  

Комментарии:

1. Хорошо, может ли это обрабатывать огромные файлы (ГБ ) и подузлы? XmlReader / Writer также пришел мне на ум 🙂

2. Не пробовал этого, но я думаю, что при достаточном количестве процессора / оперативной памяти это должно сработать;)

3. в некоторых случаях simplexml требуется в 10 раз больше памяти, чем дисковое пространство, зависит от размера и структуры.

4. Не пробовал это для файлов объемом более ГБ… может быть, я когда-нибудь это сделаю.

5. Здравствуйте, большое спасибо за ответ, он работает так, как я надеялся.

Ответ №2:

В DOM вы используете Xpath для поиска узлов, DOMDocument::create*() для создания узлов и подобных методов DOMNode::appendChild() , чтобы поместить их в документ.

 $xml =<<< END
<Root>
    <child id="1">
        <text>smth</text>
    </child>
</Root>
END;

$document = new DOMDocument("1.0");
$document->preserveWhiteSpace = false;
$document->formatOutput = true;
$document->loadXml($xml);
$xpath = new DOMXpath($document);

foreach ($xpath->evaluate('//*[@id="1"][1]') as $parentNode) {
  $parentNode
    ->appendChild($document->createElement('text'))
    ->appendChild($document->createTextNode('node value'));
}

echo $document->saveXML();
  

Вывод:

 <?xml version="1.0"?>
<Root>
  <child id="1">
    <text>smth</text>
    <text>node value</text>
  </child>
</Root>
  

Для больших XML-файлов вы можете использовать XmlReader / XmlWriter, но вы не можете изменять документ. Вам нужно будет прочитать оригинал шаг за шагом и написать измененную копию.