Сравнение 2 XML-файлов с использованием PHP


Я хочу сравнить 2 больших xml-файла и получить различия. Как это делают ExamXML и DiffDog. Решение, которое я нашел, состояло в том, чтобы одновременно просматривать все дочерние узлы каждого файла и проверять, равны ли они. Но я понятия не имею, как этого добиться... Как я могу выполнить цикл по всем дочерним узлам и их свойствам? Как я могу проверить, равен ли первый элемент первого файла первому элементу второго файла, второй элемент первого файла равен второму элементу второго файла и так далее?

У вас есть идея получше сравнить 2 xml-файла?

Author: Ben L., 2010-12-02

5 answers

Вы вообще рассматривали возможность использования XPath? Похоже, это простой способ захватить все дочерние узлы. Тогда вы сможете перебирать узлы и сравнивать атрибуты/текстовый контент.

 2
Author: Ben L., 2010-12-02 19:16:47

Это может быть очень альтернативным решением для вас, но я бы сделал это именно так.

Во-первых, я бы попытался преобразовать формат в нечто гораздо более управляемое, например в массив, чтобы преобразовать XML в массив.

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

Это какой-то простой код, чтобы сделать именно это.

Тогда PHP имеет функцию array_diff(), которая может показать вам различия.

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

Это может сработать или не сработать для вас, учитывая, что вам нужно делать с различиями, но если вы хотите просто определить их и действовать в соответствии с ними, это может быть очень быстрым решением вашей проблемы.

 2
Author: Mech Software, 2010-12-02 18:47:14

Я искал что-то, чтобы сравнить два XML, как вы, и я нашел это решение, которое работает очень хорошо.

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

Я надеюсь, что это кому-то поможет.

 2
Author: harley, 2011-08-26 13:28:40

Попробуйте расширение xmldiff

Http://pecl.php.net/xmldiff

Он основан на той же библиотеке, что и модуль perl DifferenceMarkup, вы получите XML-документ diff и даже сможете его объединить.

 1
Author: Maximilian, 2013-10-10 08:19:48
//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;      
}
 0
Author: Vicky, 2015-10-01 00:46:47