0

我在使用 xmldiff 包时遇到了一些问题。我正在使用 xmldiff 包 0.9.2;PHP 5.4.17;阿帕奇 2.2.25。

例如,我有两个 xml 文件:“from.xml”和“to.xml”。

文件“from.xml”包含:

<?xml version="1.0" encoding="UTF-8"?> 
<root>  
 <rott>   
  <NDC>321</NDC> 
  <NDC>123</NDC>  
 </rott>   
</root>

文件“to.xml”包含:

<?xml version="1.0" encoding="UTF-8"?>
<root>
 <rott>
  <NDC>123</NDC>
  <NDC>321</NDC>
 </rott>  
</root>

我正在使用代码:

$zxo = new XMLDiff\File;

$dir1 = dirname(__FILE__) . "/upload/from.xml";
$dir2 = dirname(__FILE__) . "/upload/to.xml";


$diff = $zxo->diff($dir1, $dir2);
$file = 'differences.xml';
file_put_contents($file, $diff);

我在“differences.xml”文件中得到结果:

<?xml version="1.0"?>
<dm:diff xmlns:dm="http://www.locus.cz/diffmark">
  <root>
    <rott>
      <dm:delete>
        <NDC/>
      </dm:delete>
      <dm:copy count="1"/>
      <dm:insert>
        <NDC>321</NDC>
      </dm:insert>
    </rott>
  </root>
</dm:diff>

您能否从以下位置发表评论:

<dm:delete>
  <NDC/>
</dm:delete>

来了?

另外请告知我是否有一种方法可以区分两个 xml 文件而不考虑 xml 节点顺序?

4

2 回答 2

2

您看到的是libdiffmark格式的差异。就在那个页面:

<copy/> 用于输入子树相同的地方

您的片段中的文档具有部分相同的子树。实际上,libdiffmark 将执行的指令是

  • 删除整个子树
  • 复制1个节点,这意味着两个文档中的节点相同,所以不要触摸它
  • 插入 1 个新节点

节点的顺序很重要。请考虑如果忽略节点顺序,差异会是什么样子。假设您有 42 个节点,其中一些节点是相同的,它将如何将复制指令与计数一起应用?diff 更容易使用两个文档的确切节点顺序。我在这里找到的一篇有趣的读物是关于为什么节点顺序很重要。

谢谢。

于 2014-02-27T01:17:04.547 回答
1

如果文档结构已知,我认为您可以简单地对必要的部分进行排序。这是一篇关于它的有用文章。基于它,我已经戳了一些示例,并且可以按节点值对文档进行排序(仅作为示例),请看这里

文档库.xml

<?xml version="1.0"?>
 <library>
<book id="1003">
    <title>Jquery MVC</title>
    <author>Me</author>
    <price>500</price>
</book>
<book id="1001">
    <title>Php</title>
    <author>Me</author>
    <price>600</price>
</book>
<book id="1002">
    <title>Where to use IFrame</title>
    <author>Me</author>
    <price>300</price>
</book>
<book id="1002">
    <title>American dream</title>
    <author>Hello</author>
    <price>300</price>
</book>
</library>

PHP 代码,按 <title> 排序

<?php

$dom = new DOMDocument();
$dom->load('library.xml');
$xp = new DOMXPath($dom);

$booklist = $xp->query('/library/book');
$books = iterator_to_array($booklist);


function sort_by_title_node($a, $b)
{
    $x = $a->getElementsByTagName('title')->item(0);
    $y = $b->getElementsByTagName('title')->item(0);

    return strcmp($x->nodeValue, $y->nodeValue) > 0;
}


usort($books, 'sort_by_title_node');

$newdom = new DOMDocument("1.0");
$newdom->formatOutput = true;
$root = $newdom->createElement("library");
$newdom->appendChild($root);
foreach ($books as $b) {
    $node = $newdom->importNode($b,true);
    $root->appendChild($newdom->importNode($b,true));
}

echo $newdom->saveXML();

结果如下:

<?xml version="1.0"?>
<library>
<book id="1002">
    <title>American dream</title>
    <author>Hello</author>
    <price>300</price>
</book>
<book id="1003">
    <title>Jquery MVC</title>
    <author>Me</author>
    <price>500</price>
</book>
<book id="1001">
    <title>Php</title>
    <author>Me</author>
    <price>600</price>
</book>
<book id="1002">
    <title>Where to use IFrame</title>
    <author>Me</author>
    <price>300</price>
</book>
</library>

这样,您可以在比较之前对文档的各个部分进行排序。之后你甚至可以直接使用 DOM 比较。即使您可以重新排序节点,也是一种类似的方法。

如果您有可变节点号,我不确定它是否会非常有用。假设 <NDC> 标记是否重复了一些随机次数并且它的值完全不同。

毕竟,我仍然认为最简单的方法是让你的请求者创建一些更可预测的文档结构:)

谢谢

阿纳托尔

于 2014-03-03T12:45:11.200 回答