2014-02-02 3 views
0

Пробовал много разных сценариев, и в итоге я оказался рядом с решением, но не знал, как определить его. Пробовал «@name» и «name». Все скрипты, которые я пробовал, копируются здесь и там и меняются для моего использования.merge xml childs with php

В XMLs есть 1 узел и 1 ребенок каждый. Не должно быть намного проще, чем это, но не повезло. Можно упомянуть, что я также хочу, чтобы ссылка на таблицу стилей xsl была объединена, но я думаю, что просто зашуршала над решением для этого, но забыла закладок на странице.

XML 1:

<?xml version="1.0" encoding="utf-8"?> 
<companyroutes> 
    <route name="BBUPLOAD">ENGM OKSAT L996 SVD EKCH</route> 

</companyroutes> 

XML 2:

<?xml version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 
<companyroutes> 
    <route name="XXXXCORE">RUTA TULLA L666 BARE LITT MNOP</route> 

</companyroutes> 

И код PHP (этот файл находится в том же директории, что и выходной файл:

<?php 
    $doc1 = new DOMDocument(); 
    $doc1->load('/uploads/companyroutes.xml'); 

    $doc2 = new DOMDocument(); 
    $doc2->load('/uploads/companyroutes_core.xml'); 

    // get 'res' element of document 1 
    $res1 = $doc1->getElementsByTagName('res')->name(0); 

    // iterate over '@name' elements of document 2 
    $companyroutes2 = $doc2->getElementsByTagName('name'); 
    for ($i = 0; $i < $companyroutes2->length; $i ++) { 
     $name2 = $companyroutes2->name($i); 

     // import/copy @name from document 2 to document 1 
     $name1 = $doc1->importNode($name2, true); 

     // append imported @name to document 1 'res' element 
     $res1->appendChild($name1); 

    } 
    $doc1->save('companyroutes.xml'); 
    ?> 

Любые указатели оценивается.

ответ

1

He ре, как объединить файлы с simplexml:

$xml = simplexml_load_string($x1); // assume XML in $x1 and $x2 
$xml2 = simplexml_load_string($x2); 

foreach ($xml2->route as $route) { // merge $xml2 into $xml 
    $newroute = $xml->addChild("route", $route); 
    $newroute->addAttribute("name", $route['name']); 
} 

unset($xml2); // dispose $xml2 

echo $xml->asXML(); 

видеть, что это работает: https://eval.in/97372

+0

Будут ли $ x1 и $ x2 быть URL-адресами двух файлов xml? Вроде: $ x1 = ('/uploads/companyroutes.xml'); – NAX

+0

@NAX в моем примере, это строки. Посмотрите на ссылку в моем ответе. Вместо этого вы можете использовать simplexml_load_file с именами файлов. – michi

+0

Поэтому я просто меняю первые две строки: $ xml = simplexml_load_file ('/ uploads/companyroutes_core.xml'); ... и $ xml2 = simplexml_load_file ('/ uploads/companyroutes.xml') ... Могу ли я добавить строку после команды echo, чтобы скрипт копировал результат xml и вставлял его в Companyroutes_core.xml? Мне нужна эта функция, чтобы гарантировать, что результат xml является ядром для следующего слияния. /uploads/companyroutes.xml загружается многими пользователями, добавляя их новые записи в объединенный файл.Если ядро ​​не обновлено, новые записи будут потеряны при загрузке и слиянии следующего пользователя. Возможно, файл_put? – NAX

1

Два шага, подготовить целевой DOM (добавить элемент документа). Загрузите каждый исходный XML, траверс дочерние узлы внутри элемента документа и импортировать их в целевой документ:

$xmlFiles = [ 
    '/uploads/companyroutes.xml', 
    '/uploads/companyroutes_core.xml' 
]; 

$targetDom = new DOMDocument(); 
$targetDom->appendChild(
    $targetDom->createProcessingInstruction(
    'xml-stylesheet', 'type="text/xml" href="merge2.xsl"' 
) 
); 
$rootNode = $targetDom->appendChild(
    $targetDom->createElement('companyroutes') 
); 

foreach ($xmlFiles as $xmlFile) { 
    $importDom = new DOMDocument(); 
    $importDom->load($xmlFile); 
    foreach ($importDom->documentElement->childNodes as $node) { 
    $rootNode->appendChild($targetDom->importNode($node, TRUE)); 
    } 
} 

echo $targetDom->saveXml(); 

пример с XML-строки в качестве источников: https://eval.in/97405

Конечно, вы можете создать шаблон XML для целевой DOM и просто загрузить его:

$template = <<<'XML' 
<?xml version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 
<companyroutes/> 
XML; 

$targetDom = new DOMDocument(); 
$targetDom->loadXml($template); 
$rootNode = $targetDom->documentElement; 
... 

Я бы не предложил изменить документ. Если вы создадите новый документ, вы можете повторить действие.

+0

Я могу рассказать о первом сценарии здесь, так как я понимаю все строки. Я проверю это позже сегодня. – NAX

+0

Второй пример показывает альтернативу созданию $ targetDom и присваивает переменную $ rootNode, загружая шаблон xml. – ThW

0

Спасибо. Я сделал небольшое редактирование и запустил его.

$xml = simplexml_load_file('./uploads/companyroutes_core.xml'); // xml files URL insted of $x 
$xml2 = simplexml_load_file('./uploads/companyroutes.xml'); 

foreach ($xml2->route as $route) { // merge $xml2 into $xml 
    $newroute = $xml->addChild("route", $route); 
    $newroute->addAttribute("name", $route['name']); 
} 

unset($xml2); // dispose $xml2 

$xml->asXML('merged.xml'); //this line saves to directory and name of choice 

Моя единственная проблема в том, что все дочерние элементы выводятся на одной отдельной линии. 4-мегабайтная длинная линия. Нужно, чтобы он был более аккуратным (да, я читал о аккуратных командах, но как использовать его здесь ...? Idunno) и разбить его для каждого ребенка. Спасибо за терпение. Не удивляйтесь, если вы видите, что я задаю более простые вопросы, но хорошо то, что я больше узнаю каждый день, когда я борюсь с ним.

+0

@michi Возможно ли вставить команду только для объединения уникальных записей? Я нашел пример использования массива и только слияние уникальных дочерних элементов, но не могу напрямую вставлять эти строки в этот скрипт. Может ли функция этого скрипта быть выполнена с использованием массивов? – NAX