我想比较 2 个大 xml 文件并检索差异。就像 ExamXML 和 DiffDog 一样。我找到的解决方案是同时循环遍历每个文件的所有子节点并检查它们是否相等。但我不知道如何实现这一点......我怎样才能遍历所有子节点及其属性?如何检查第一个文件的第一个元素是否等于第二个文件的第一个元素,第一个文件的第二个元素是否等于第二个文件的第二个元素等等?
你有更好的主意来比较 2 个 xml 文件吗?
我一直在寻找一些东西来比较像你这样的两个 XML,我发现这个解决方案效果很好。
http://www.jevon.org/wiki/Comparing_Two_SimpleXML_Documents
我希望这对某人有所帮助。
Have you looked at using XPath at all? Seems like an easy way to grab all of the child nodes. Then you'd be able to loop through the nodes and compare the attributes/textContent.
这对您来说可能是一个非常替代的解决方案,但这就是我的做法。
首先,我会尝试将格式转换为更易于管理的格式,例如数组,因此我会将 XML 转换为数组。
http://www.bytemycode.com/snippets/snippet/445/
这是一些简单的代码来做到这一点。
然后 PHP 有一个 array_diff() 函数可以显示差异。
http://www.php.net/manual/en/function.array-diff.php
考虑到您需要如何处理这些差异,这可能对您有用,也可能不适用,但如果您只想识别它们并对其采取行动,这可能是解决您问题的一个非常快速的解决方案。
试试 xmldiff 扩展
它基于与 perl 模块 DifferenceMarkup 相同的库,您将获得一个 diff XML 文档,甚至可以合并。
//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;
}