Мне нужно реализовать следующий алгоритм с SimpleXML:
ПРОБЛЕМЫ:
Как загрузить XML с именованными объектами (например, ).
Чтобы перемещаться по XML, чтобы получить только текстовые узлы … С $sx->xpath('//text()'); Я не могу редактировать узлы, как выбрать текстовые узлы для выпуска?
Вы можете переопределить текстовое содержимое узла, возвращаемого запросом SimpleXML XPath, назначив $node[0] , например
foreach ( $sx->xpath('//text()') as $text_node ) { $text_node[0] = 'Hello'; }
Однако будьте осторожны, что SimpleXML действительно не имеет представления текстового узла как такового, поэтому такой тип цикла будет вести себя странно, если в элементе есть как дочерние элементы, так и текст.
Например, учитывая XML <a><b>foo<c />bar</b><b>baz quux</b></a> , два текстовых узла, содержащих foo и bar , оба будут представлены в SimpleXML посредством первый элемент <b> , все содержимое которого будет заменено на 'Hello' , дважды, как показано ниже ( живая демонстрация здесь ). Используя переменную счетчика в замещаемом тексте, мы можем ясно видеть, что происходит – желаемый результат будет <a><b>Hello 1<c />Hello 2</b><b>Hello 3</b></a> , но фактическим результатом является <a><b>Hello 2</b><b>Hello 3</b></a> .
$sx = simplexml_load_string('<a><b>foo<c />bar</b><b>baz quux</b></a>'); $counter = 1; foreach ( $sx->xpath('//text()') as $text_node ) { $text_node[0] = 'Hello ' . $counter++; } echo $sx->asXML();
Подобная манипуляция, по крайней мере, по мере того, как вы создавали проблему (поиск текстовых узлов, а не повторение, возможно, рекурсивно, по определенному набору элементов) гораздо более подходит для DOM API, чем для SimpleXML. Имейте в виду, что между ними нет разницы в производительности (они оба являются обертками вокруг одного и того же синтаксического анализатора XML) и что вы можете комбинировать операции с использованием двух API в одном документе с помощью simplexml_import_dom() и dom_import_simplexml() , без дополнительные накладные расходы, поскольку документ не нуждается в повторном анализе.
Вот приведенный выше пример, зафиксированный с использованием смеси SimpleXML и DOM ( live demo ). Если бы это был весь код, вы могли просто анализировать DOM напрямую, но это демонстрирует, как легко их смешивать, если у вас уже есть другой код, управляющий этим документом с помощью SimpleXML. Обратите внимание, что в конце мы выводим XML с использованием исходного объекта SimpleXML – нам не нужно запускать simplexml_import_dom($dom) , потому что оба объекта относятся к одному и тому же анализируемому «документу» в памяти.
$sx = simplexml_load_string('<a><b>foo<c />bar</b><b>baz quux</b></a>'); $dom = dom_import_simplexml($sx); $counter = 1; $xpath = new DOMXpath($dom->ownerDocument); foreach ( $xpath->query('//text()') as $text_node ) { $text_node->nodeValue = 'Hello ' . $counter++; } echo $sx->asXML();