使用PHP比较2个XML文件

时间:2010-12-02 18:25:48

标签: php xml compare nodes

我想比较两个大的xml文件并检索差异。像ExamXML和DiffDog一样。我找到的解决方案是同时循环遍历每个文件的所有子节点,并检查它们是否相等。但我不知道如何实现这一点......我如何遍历所有子节点及其属性?如何检查第一个文件的第一个元素是否等于第二个文件的第一个元素,第一个文件的第二个元素是否等于第二个文件的第二个元素,依此类推?

你有更好的想法来比较2个xml文件吗?

5 个答案:

答案 0 :(得分:2)

这可能是一个非常替代的解决方案,但这就是我要做的。

首先,我尝试将格式化为像数组更易于管理的内容,以便将XML转换为数组。

http://www.bytemycode.com/snippets/snippet/445/

这是一些简单的代码。

然后PHP有一个array_diff()函数,可以显示差异。

http://www.php.net/manual/en/function.array-diff.php

考虑到您需要对差异做些什么,这可能会或可能不会对您有所帮助,但如果您只想识别并采取行动,这可能是您问题的快速解决方案。

答案 1 :(得分:2)

你有没有看过使用XPath?看起来像抓住所有子节点的简单方法。然后,您将能够遍历节点并比较属性/ textContent。

答案 2 :(得分:2)

我正在寻找能够比较像你这样的两个XML的东西,而且我发现这个解决方案效果非常好。

http://www.jevon.org/wiki/Comparing_Two_SimpleXML_Documents

我希望对某人有所帮助。

答案 3 :(得分:1)

尝试xmldiff扩展

http://pecl.php.net/xmldiff

它基于与perl模块DifferenceMarkup相同的库,你将得到一个diff XML文档,甚至可以合并。

答案 4 :(得分:0)

//Child by Child XML files comparison in PHP  
//Returns an array of non matched children in variable &$reasons

$reasons = array();
$xml1 = new SimpleXMLElement(file_get_contents($xmlFile1));
$xml2 = new SimpleXMLElement(file_get_contents($xmlFile2));
$result = XMLFileComparison($xml1, $xml2, $reasons);

/**
 * XMLFileComparison
 * Discription :- This function compares XML files. Returns array
 * of nodes do not match in pass by reference parameter
 * @param $xml1 Object Node Object
 * @param $xml2 Object Node Object
 * @param &$reasons Array  pass by reference 
 * returns array of nodes do not match
 * @param $strict_comparison Bool  default False
 * @return bool <b>TRUE</b> on success or array of strings on failure.
 */
function XMLFileComparison(SimpleXMLElement $xml1, SimpleXMLElement   $xml2, &$reasons, $strict_comparison = false)        
{
    static $str;  
    // compare text content
    if ($strict_comparison) {
        if ("$xml1" != "$xml2") return "Values are not equal (strict)";
    } else {
        if (trim("$xml1") != trim("$xml2"))
                {
                    return " Values are not equal";
                }
    }


    // get all children
    $XML1ChildArray = array();
    $XML2ChildArray = array();
    foreach ($xml1->children() as $b) {
        if (!isset($XML1ChildArray[$b->getName()]))
            $XML1ChildArray[$b->getName()] = array();
        $XML1ChildArray[$b->getName()][] = $b;
    }
    foreach ($xml2->children() as $b) {
        if (!isset($XML2ChildArray[$b->getName()]))
            $XML2ChildArray[$b->getName()] = array();
        $XML2ChildArray[$b->getName()][] = $b;
    }
    //print_r($XML1ChildArray);
    //print_r($XML2ChildArray);
    // cycle over children
    if (count($XML1ChildArray) != count($XML2ChildArray)) return "mismatched children count";// Second File has less or more children names (we don't have to search through Second File's children too)
    foreach ($XML1ChildArray as $child_name => $children) {
        if (!isset($XML2ChildArray[$child_name])) return "Second file does not have child $child_name"; // Second file has none of this child
        if (count($XML1ChildArray[$child_name]) != count($XML2ChildArray[$child_name])) return "mismatched $child_name children count"; // Second file has less or more children

                print_r($child_name);
                foreach ($children as $child) {
            // do any of search2 children match?
            $found_match = false;
            //$reasons = array();
            foreach ($XML2ChildArray[$child_name] as $id => $second_child) {
                            $str = $str.$child_name.($id+1)."/"; // Adding 1 to $id to match with XML data nodes numbers
                            //print_r($child, $second_child);
                            // recursive function call until reach to the end of node
                if (($r = XMLFileComparison($child, $second_child, $reasons, $strict_comparison)) === true) {
                    // found a match: delete second
                    $found_match = true;
                    unset($XML2ChildArray[$child_name][$id]);
                                        $str = str_replace($child_name.($id+1)."/", "", $str);
                                        break;
                } 
                                else {
                                    unset($XML2ChildArray[$child_name][$id]);
                                    $reasons[$str] = $r;
                                    $str = str_replace($child_name.($id+1)."/", "", $str);
                                    break;
                }
            }

        }
    }
  return True;      
}