Tutorial :SimpleXML - add a new node using a namespace previously declared - how?



Question:

I would like to add a child, on a very specific place (so I'm also using DOM and not only simpleXML) for <domain:create> node.

I have tried to use the $ns attribute on simpleXML construct.

$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);  

But I'm getting:

I/O warning : failed to load external entity "<domain:ns>"

I've tried to register the prefix after creating the element, but I use no xpath after this, so this was quite a useless try...

//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');  

Since the xml is loaded from a file, and that file as this ns declared, maybe we should grab it from that file?

Here is an overall of the above, so that we can better understand the context: We are loading a XML file that contains an overall structure:

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

They we will grab an element that we will use as a target:

//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);  

Now we have our node placed on a proper place. And converted to simpleXML so, we can now easily add some children and fill the rest of the xml file..

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

Please advice, MEM


Solution:1

<?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);  }  

prints

<?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>  


Solution:2

Since the xml is loaded from a file, and that file as this ns declared, maybe we should grab it from that file?

If that file is a XML file, yes, you should load the whole the file, not just a portion.

Once the namespace is declared, adding a namespaced element is easy:

<?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();  

gives

<?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>  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »