2012-04-15 44 views
17

我有兩個文件1.xml2.xml都具有相似的結構,我想有一個。我嘗試了很多解決方案,但我只有錯誤 - 坦率地說,我不知道這些腳本是如何工作的。在PHP中合併XML文件

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> 

我想創建一個新的文件merged.xml結構如下

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

我應該怎麼辦呢?你能解釋一下嗎?我怎樣才能做到更多的文件?由於

編輯

我試過嗎?

<?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的意見,我看着DOM文檔手冊,發現了一個例子:

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

但它會創建錯誤的XML文件:

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

我無法正確使用此文件。我需要正確的結構,在這裏我有一種粘貼到另一個文件。我想「粘貼」只是項目的不是所有的標籤。我應該改變什麼?

EDIT3

這裏是一個答案 - 基於Torious答案 - 只要它適合我的需要 - 檢查//編輯

$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

嘗試使用DOM,啓動[這裏](http://www.php.net/manual/en/domdocument.loadxml.php)。請注意,如果要合併XML文檔(來自不同的'DOMDocument'源,則必須在某個時間點使用'importNode'(大約) – Torious 2012-04-15 16:40:57

回答

17

既然你已經把一個努力,我編寫應該起作用的東西。

請注意,這是未經測試的代碼,但您明白了。

這取決於你使它成爲漂亮的功能。確保你明白髮生了什麼;能夠使用DOM可能會幫助你在很多未來的場景中。關於DOM標準的一個很酷的事情是,你在許多不同的編程語言/平臺上有幾乎相同的操作。

$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用於執行無聊dom轉換 – worenga 2012-04-15 19:10:52

+0

感謝您的解決方案 - 我不得不改變一些東西 - 檢查編輯3部分/ /編輯 - 意味着我改變了行 – andrewpo 2012-04-15 19:50:26

+0

忘了它再次感謝 – andrewpo 2012-04-15 20:52:07

-2

如何:

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

我認爲最簡單的辦法就是先改變XML到陣列,將兩個陣列是更容易和簡單。最後將數組更改回xml。它可能有助於您想要直接合並兩個XML文件的情況。你只需要考慮哪個鍵是你想添加子節點的位置。

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

用途:創建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);