(PHP) Добавление новых дочерних элементов XML с префиксом пространства имен

У меня есть XML, который имеет t:subscriptions элемент, который содержит несколько t:subscription дочерние элементы.

Моя главная цель — заменить текущий t:subsciptions в целом или все t:subsciption элементы с новыми. На данный момент я создал новый t:subscription элементы в виде строк (не разбирались в классах dom / simplexml, поэтому мне пришлось использовать метод «отступления»).

Теперь я пытаюсь преобразовать строку в XML с помощью simplexml_load_string, а затем dom_import_simplexml, чтобы добавить / заменить текущие подписки в XML. Я пробовал следующий пример, найденный с этого сайта:

$newsubs = ''; //new XML as string

$sdom = new DOMDocument();
$sdom->loadXML($xml->asXML()); // current XML
//dpm($sdom->saveXML());
$xpath = new DOMXPath($sdom);

// ... x functions generate $newsubs string ...

$remove = $sdom->getElementsByTagName('subscriptions')->item(0); // get t:subscriptions for removal
$remove->parentNode->removeChild($remove); // remove t:subscriptions
$fragment = $sdom->createDocumentFragment();
$fragment->appendXml($newsubs);
$xpaths
->evaluate('//t:member')        // this node holds t:subscriptions among others
->item(0) // there's always only one member node
->appendChild($fragment);
debug($sdom->saveXML());

Я зашел так далеко, что только ошибка получена Namespace prefix X on Y is not defined и это для всех элементов. Скрипт удаляет префиксы пространства имен, хотя они определены в строке XML, например <t:myelement>asdasd</t:myelement>,

Документ XML, к которому будет добавлен этот XML, уже имеет префикс. Я не понимаю, почему он не может принять префиксный XML и удаляет префикс, а новый документ добавляется в документ? Не имеет смысла

1

Решение

Сообщение об ошибке может означать, что атрибут «xmlns: *» для пространства имен отсутствует в XML или что префикс пространства имен не был зарегистрирован в объекте XPath.

XML-документ

Пространства имен должны быть определены с обеих сторон. Первый — это сам XML.

<foo xmlns="urn:foo"/>

или же

<f:foo xmlns:f="urn:foo"/>

Обе команды разрешаются парсером в одно и то же пространство имен и локальное имя. Вы можете прочитать имя элемента как {urn:foo}:foo,

Вот несколько * NS-методов в DOM, которые позволяют вам работать с пространством имен. Пространство имен всегда URN. Префикс не подходит для сопоставления.

$node->getElementsByTagNameNS('urn:foo', 'foo')

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

$document->createElementNS('urn:foo', 'foo'); // no prefix
$document->createElementNS('urn:foo', 'f:foo'); // with prefix "f"

XPath

XPath также использует префиксы в выражениях. Но это не должно читать их из документа. использование DOMXpath::registerNamespace() зарегистрировать собственные префиксы для определенного пространства имен.

пример

В вашем вопросе отсутствует полный XML, поэтому я добавлю небольшой пример Atom. Вы можете видеть, что пространство имен одинаково в XML и в PHP, но префикс отличается:

$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
<atom:title>Example Feed</atom:title>
<atom:entry>
<atom:title>Atom-Powered Robots Run Amok</atom:title>
<atom:id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</atom:id>
</atom:entry>
</atom:feed>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('a', 'http://www.w3.org/2005/Atom');

var_dump($xpath->evaluate('string(//a:entry/a:title)'));

Выход:

string(28) "Atom-Powered Robots Run Amok"
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]