2012-04-15 4 views
17

Ich habe 2 Dateien 1.xml und 2.xml beide ähnliche Struktur und ich möchte eine haben. Ich habe viele Lösungen ausprobiert, aber ich hatte nur Fehler - ehrlich gesagt habe ich keine Ahnung, wie diese Skripte funktionieren.Merge XML-Dateien in PHP

1.xml:

<res> 
    <items total="180"> 
     <item> 
      <id>1</id> 
      <title>Title 1</title> 
      <author>Author 1</author> 
     </item> 
     ... 
    </items> 
</res> 

2.xml:

<res> 
    <items total="123"> 
     <item> 
      <id>190</id> 
      <title>Title 190</title> 
      <author>Author 190</author> 
     </item> 
     ... 
    </items> 
</res> 

Ich mag würde eine neue Datei merged.xml mit folgenden Struktur schaffen

<res> 
    <items total="303"> 
     <item> 
      <id>1</id> 
      <title>Title 1</title> 
      <author>Author 1</author> 
     </item> 
     ... //items from 1.xml 
     <item> 
      <id>190</id> 
      <title>Title 190</title> 
      <author>Author 190</author> 
     </item> 
     ... //items from 2.xml 
    </items> 
</res> 

Wie soll ich das tun? Kannst du mir den Weg erklären? Wie kann ich es mit mehr Dateien machen? Dank

bearbeiten

Was habe ich versucht?

<?php 
function mergeXML(&$base, $add) 
{ 
    if ($add->count() != 0) 
    $new = $base->addChild($add->getName()); 
    else 
     $new = $base->addChild($add->getName(), $add); 
    foreach ($add->attributes() as $a => $b) 
    { 
     $new->addAttribute($a, $b); 
    } 
    if ($add->count() != 0) 
    { 
     foreach ($add->children() as $child) 
     { 
      mergeXML($new, $child); 
     } 
    } 
} 
$xml = mergeXML(simplexml_load_file('1.xml'), simplexml_load_file('2.xml')); 
echo $xml->asXML(merged.xml); 
?> 

EDIT2

Torious Beratung Nach schaute ich in DOMDocument Handbuch und ein Beispiel gefunden:

function joinXML($parent, $child, $tag = null) 
{ 
    $DOMChild = new DOMDocument; 
    $DOMChild->load($child); 
    $node = $DOMChild->documentElement; 

    $DOMParent = new DOMDocument; 
    $DOMParent->formatOutput = true; 
    $DOMParent->load($parent); 

    $node = $DOMParent->importNode($node, true); 

    if ($tag !== null) { 
     $tag = $DOMParent->getElementsByTagName($tag)->item(0); 
     $tag->appendChild($node); 
    } else { 
     $DOMParent->documentElement->appendChild($node); 
    } 

    return $DOMParent->save('merged.xml'); 
} 

joinXML('1.xml', '2.xml') 

Aber es schafft falsche XML-Datei:

<res> 
    <items total="180"> 
     <item> 
      <id>1</id> 
      <title>Title 1</title> 
      <author>Author 1</author> 
     </item> 
     ... 
    </items> 
    <res> 
     <items total="123"> 
      <item> 
       <id>190</id> 
       <title>Title 190</title> 
       <author>Author 190</author> 
      </item> 
      ... 
     </items> 
    </res> 
</res> 

Und ich kann diese Datei nicht korrekt verwenden. Ich brauche eine korrekte Struktur und hier habe ich irgendwie eine Datei in eine andere einfügen. Ich möchte nur die nicht alle Tags des Elements "einfügen". Was soll ich ändern?

EDIT3

hier ist eine Antwort - basierend auf Torious Antwort - angepasst es nur auf meine Bedürfnisse - überprüfen // bearbeitet

$doc1 = new DOMDocument(); 
$doc1->load('1.xml'); 

$doc2 = new DOMDocument(); 
$doc2->load('2.xml'); 

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

// iterate over 'item' elements of document 2 
$items2 = $doc2->getElementsByTagName('item'); 
for ($i = 0; $i < $items2->length; $i ++) { 
    $item2 = $items2->item($i); 

    // import/copy item from document 2 to document 1 
    $item1 = $doc1->importNode($item2, true); 

    // append imported item to document 1 'res' element 
    $res1->appendChild($item1); 

} 
$doc1->save('merged.xml'); //edited -added saving into xml file 
+0

Versuchen Sie das DOM verwenden, starten Sie [hier] (http://www.php.net/manual/en/domdocument.loadxml.php). Beachten Sie, dass Sie, wenn Sie XML-Dokumente (aus verschiedenen 'DOMDocument'-Quellen zusammenführen möchten, zu irgendeinem Zeitpunkt' ImportNode' (oder so) verwenden müssen. – Torious

Antwort

17

Da Sie eine Anstrengung in gesetzt habe, habe ich codiert etwas, das funktionieren sollte.

Beachten Sie, dass dies ungeprüfter Code ist, aber Sie erhalten die Idee.

Es liegt an Ihnen, es in hübsche Funktionen zu machen. Stellen Sie sicher, dass Sie verstehen, was vor sich geht. Die Möglichkeit, mit dem DOM zu arbeiten, wird Ihnen wahrscheinlich in vielen Zukunftsszenarien helfen. Das Tolle am DOM-Standard ist, dass Sie in vielen verschiedenen Programmiersprachen/Plattformen so ziemlich die gleichen Operationen haben.

$doc1 = new DOMDocument(); 
    $doc1->load('1.xml'); 

    $doc2 = new DOMDocument(); 
    $doc2->load('2.xml'); 

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

    // iterate over 'item' elements of document 2 
    $items2 = $doc2->getElementsByTagName('item'); 
    for ($i = 0; $i < $items2->length; $i ++) { 
     $item2 = $items2->item($i); 

     // import/copy item from document 2 to document 1 
     $item1 = $doc1->importNode($item2, true); 

     // append imported item to document 1 'res' element 
     $res1->appendChild($item1); 

    } 
+0

+1 für langweilige dom-Übersetzungen – worenga

+0

danke für die Lösung - Ich musste ein paar Dinge ändern - check edit3 section // edit - bedeutet, dass ich eine Zeile geändert habe – andrewpo

+0

habe es vergessen danke nochmal – andrewpo

-2

Wie wäre:

<?php 
// Read file 1 
$xmlfilecontent = file_get_contents('xml1.xml'); 

// Concat file 2 
$xmlfilecontent .= file_get_contents('xml2.xml'); 

// remove <items> tags 
preg_replace('/<items[^"]*">/','',$xmlfilecontent); 

// remove </items> tags 
$xmlfilecontent = str_replace('</items>','',$xmlfilecontent); 

// remove <res> tags 
$xmlfilecontent = str_replace('<res>','',$xmlfilecontent); 

// remove </res> tags 
$xmlfilecontent = str_replace('</res>','',$xmlfilecontent); 

// load XML Object - also add res and items + amount 
$xmlobj = simple_xml_load_string('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'.PHP_EOL.'<res>'.PHP_EOL.'<items total="'.substr_count($xmlfilecontent , '<item>').'">'.PHP_EOL.$xmlfilecontent.PHP_EOL.'</items>'.PHP_EOL.'</res>'); 
0

ich denke, die einfachste Art und Weise erste XML-Array verändert sich, kombinieren zwei Array, das viel einfacher und unkompliziert sind. Ändern Sie das Array schließlich wieder in XML. Dies kann hilfreich sein, wenn Sie zwei XML-Dateien direkt kombinieren möchten. Sie müssen nur berücksichtigen, welcher Schlüssel die Position ist, an der Sie die untergeordneten Knoten hinzufügen möchten.

function xml_to_array($sxi){ 
    $a = array(); 
    for($sxi->rewind(); $sxi->valid(); $sxi->next()) { 
     if(!array_key_exists($sxi->key(), $a)){ 
      $a[$sxi->key()] = array(); 
     } 
     if($sxi->hasChildren()){ 
      $a[$sxi->key()] = $this->xml_to_array($sxi->current()); 
     } 
     else{ 
      $a[$sxi->key()] = strval($sxi->current()); 
     } 
    } 
    return $a; 
} 
function array_to_xml($data, &$xml_data) { 
    foreach($data as $key => $value) { 
     if(is_numeric($key)){ 
      $key = 'item'.$key; //dealing with <0/>..<n/> issues 
     } 
     if(is_array($value)) { 
      $subnode = $xml_data->addChild($key); 
      array_to_xml($value, $subnode); 
     } else { 
      $xml_data->addChild("$key",htmlspecialchars("$value")); 
     } 
    } 
} 

Useage: Erstellen Sie eine SimpleXMLIterator

$xml1 = new \SimpleXMLIterator('test1.xml',null,true); 
$a = xml_to_array($xml1); //convert xml to array 
$xml2 = new \SimpleXMLIterator('test2.xml',null,true); 
$b = xml_to_array($xml2); 
$c = new SimpleXMLElement('<?xml version="1.0"?><data></data>'); 
$a['new_node']=$b; 
array_to_xml($a,$c); 
var_dump($c);