2010-08-09 3 views
2

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

Я хотел бы добавить ребенка, на очень конкретном месте (так я также использую 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); 

Но я получаю:

предупреждение

I/O: не удалось загрузить внешний Entity "<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

+0

Вы можете разместить небольшой автономный пример показывает вашу проблему? По крайней мере, я немного смущен тем, что происходит где и почему. Например. '$ NodeRegistrant'? Откуда это происходит? – VolkerK

+0

Конечно. Немедленно. Было довольно сложно отрезать часть ее, чтобы поставить ее в качестве вопроса.Я добавлю дополнительную информацию. 5 мин. – MEM

ответ

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

Я изучаю это ... :) Мне понадобится пару часов. Да, я такой манекен. – MEM

+0

Привет, ребята, пожалуйста, ответьте на этот вопрос: 1) Оба ваших ответа были в форме функции. Зачем? Да, это очень простой вопрос, но я тоже очень простой кодер, так как у меня не более 1 года опыта в этом. : s Еще раз спасибо MEM – MEM

+0

Сомнения 2: Зачем создавать элементы ('domain: ns'); работает, и этот importNode (dom_import_simplexml ($ nsNode), true); нет? – MEM

2

Поскольку 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

Да. Я загружаю XML из файла. Использование addChild - приятная функция, однако я не могу использовать ее в этом случае, потому что она поместит наш добавленный узел * в конец * всех братьев и сестер, однако это нужно разместить после узел. Любой другой способ архивировать это, но, не полагаясь на «addChild»? K. С уважением, MEM – MEM

+0

@MEM Смотрите этот вопрос: http://stackoverflow.com/questions/3432358/using-addchild-with-an-index-position/3432441#3432441 Вы только должны использовать DOMDocument: : createElementNS вместо DOMDocument :: createElement – Artefacto

+0

@Artefacto: Я ожидал, что это даже вопрос одного и того же пользователя ;-) Так или иначе, это _bit_ другое. В этом случае это не позиционный индекс, а 'необходимо размещать после node'. @MEM: Вопрос: всегда ли существует домен: элемент регистрации? Если нет правила возврата? – VolkerK

Смежные вопросы