【问题标题】:Merge XML files in PHP在 PHP 中合并 XML 文件
【发布时间】:2012-04-27 03:59:10
【问题描述】:

我有 2 个文件 1.xml2.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 的建议,我查看了 DOMDocument 手册并找到了一个示例:

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 的答案 - 刚刚根据我的需要进行了调整 - 检查 //edited

$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

【问题讨论】:

  • 尝试使用 DOM,开始here。请注意,如果您想合并 XML 文档(来自不同的 DOMDocument 源,则必须在某个时间点使用 importNode(或左右)。

标签: php xml merge


【解决方案1】:

既然你已经付出了努力,我已经编写了一些应该可以工作的代码。

请注意,这是未经测试的代码,但你明白了。

将它变成漂亮的函数取决于你。确保您了解正在发生的事情;能够使用 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);

    }

【讨论】:

  • 谢谢你的解决方案 - 我不得不改变一些东西 - 检查 edit3 部分 //edit - 意味着我改变了一行
  • 你可以遍历DOMNodeList,所以你的for循环最好写成foreach($doc2-&gt;getElementsByTagName('item') as $item2)
【解决方案2】:

我认为最简单的方法是先将 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);

【讨论】:

    【解决方案3】:

    怎么样:

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

    【讨论】:

      猜你喜欢
      • 2017-12-10
      • 2018-07-04
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 2011-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多