SimpleXML - добавить новый узел, используя ранее объявленное пространство имен - как? - PullRequest
2 голосов
/ 09 августа 2010

Я хотел бы добавить дочернего элемента в очень конкретном месте (поэтому я также использую DOM, а не только simpleXML) для узла <domain:create>.

Я пытался использовать атрибут $ ns в конструкции simpleXML.

$nsNode = new SimpleXMLElement('<domain:ns>', $options = 0, $ns='urn:ietf:params:xml:ns:domain-1.0');

//transform the target into dom object for manipulation
$nodeRegistrantDom = dom_import_simplexml($nodeRegistrant);

Но я получаю:

Предупреждение ввода / вывода: не удалось загрузить внешний юридическое лицо "<domain:ns>"

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

//creates the simpleXML object node to be inserted.
$nsNode = new SimpleXMLElement('<ns/>');

//this will not work, because we will not use xpath after it :s
$nsNode->registerXPathNamespace('domain', 'urn:ietf:params:xml:ns:domain-1.0');

Поскольку xml загружается из файла и этот файл объявлен этим ns, может быть, мы должны извлечь его из этого файла?

Вот общее из вышеперечисленного, чтобы мы могли лучше понять контекст: Мы загружаем файл XML, который содержит общую структуру:

 $xmlObj = simplexml_load_file('EppCreateDomain.xml');

Они возьмут элемент, который мы будем использовать в качестве цели:

//grab the target.
    $nodeRegistrant = $xmlObj->command->create->children(self::OBJ_URI_DOMAIN)->create->registrant;

    //transform the target into a dom object for later manipulation
    $nodeRegistrantDom = dom_import_simplexml($nodeRegistrant);

//we try to use simpleXML to create the node that we want to add after our target.
    $nsNode = new SimpleXMLElement('<domain:ns>');


//grabs the node and all his children (none in this case), by importing the node we want to add,
//into the root object element that contains the <domain:registrant> node.
$nsNodeDom = $nodeRegistrantDom->ownerDocument->importNode(dom_import_simplexml($nsNode), true);

$nodeRegistrantDom->parentNode->insertBefore($nsNodeDom, $nodeRegistrantDom->nextSibling);

$simpleXmlNsNode = simplexml_import_dom($nsNodeDom);

Теперь наш узел размещен в нужном месте. И преобразовано в simpleXML, теперь мы можем легко добавить несколько дочерних элементов и заполнить оставшуюся часть XML-файла.

$hostAttr = $simpleXmlNsNode->addChild('domain:hostAttr');
$hostName = $hostAttr->addChild('domain:hostName');

Пожалуйста, совет, MEM

Ответы [ 2 ]

2 голосов
/ 09 августа 2010

Поскольку xml загружен из файла, и этот файл, как объявил этот ns, может быть, мы должны извлечь его из этого файла?

Если этот файл является файлом XML, то да, вы должны загрузить весь файл, а не только его часть.

Как только пространство имен объявлено, добавить элемент пространства имен легко:

<?php
$xml = <<<XML
<epp>
    <domain:create xmlns:domain="urn:someurn" xmlns:ietf="urn:thaturn">
       <domain:name></domain:name>
       <domain:registrant></domain:registrant>
       <domain:contact></domain:contact>
    </domain:create>
</epp>
XML;

$sxml = new SimpleXMLElement($xml);
$sxml->children("domain", true)->create->addChild("newElem", "value", "urn:thaturn");
echo $sxml->saveXML();

дает

<?xml version="1.0"?>
<epp>
    <domain:create xmlns:domain="urn:someurn" xmlns:ietf="urn:thaturn">
       <domain:name/>
       <domain:registrant/>
       <domain:contact/>
    <ietf:newElem>value</ietf:newElem></domain:create>
</epp>
0 голосов
/ 09 августа 2010
<?php
// test document, registrant as first/last element and somewhere in between
$xmlObj = new SimpleXMLElement('<epp>
  <domain:create xmlns:domain="urn:someurn">
    <domain:name></domain:name>
    <domain:registrant></domain:registrant>
    <domain:contact></domain:contact>
  </domain:create>
  <domain:create xmlns:domain="urn:someurn">
    <domain:name></domain:name>
    <domain:contact></domain:contact>
    <domain:registrant></domain:registrant>
  </domain:create>
  <domain:create xmlns:domain="urn:someurn">
    <domain:registrant></domain:registrant>
    <domain:name></domain:name>
    <domain:contact></domain:contact>
  </domain:create>
</epp>');

foreach( $xmlObj->children("urn:someurn")->create as $create ) {
  $registrant = $create->registrant;
  insertAfter($registrant, 'domain:ns', 'some text');
}
echo $xmlObj->asXML();

function insertAfter(SimpleXMLElement $prevSibling, $qname, $val) {
  $sd = dom_import_simplexml($prevSibling);
  $newNode = $sd->ownerDocument->createElement($qname, $val);
  $newNode = $sd->parentNode->insertBefore($newNode, $sd->nextSibling);
  return simplexml_import_dom($newNode);
}

печать

<?xml version="1.0"?>
<epp>
  <domain:create xmlns:domain="urn:someurn">
    <domain:name/>
    <domain:registrant/><domain:ns>some text</domain:ns>
    <domain:contact/>
  </domain:create>
  <domain:create xmlns:domain="urn:someurn">
    <domain:name/>
    <domain:contact/>
    <domain:registrant/><domain:ns>some text</domain:ns>
  </domain:create>
  <domain:create xmlns:domain="urn:someurn">
    <domain:registrant/><domain:ns>some text</domain:ns>
    <domain:name/>
    <domain:contact/>
  </domain:create>
</epp>
...