如何比较两个 XML 文件并使用 Ruby 以 html 格式显示差异

How to compare two XML files and display the differences in html format using Ruby

我的 PC 上存储了一系列 xml 文件。我使用 gem Nokogiri 存储了这些文件的内容。我需要一次比较这两个 xml 的内容。如果 xml 文件之间存在差异,我想在漂亮的 html 报告中显示这些差异以供其他人查看。

有谁知道如何做到这一点?

我正在比较的第一个 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<SourceDetails>
    <Origin>Origin</Origin>
    <Identifier>Identifier</Identifier>
    <Timestamp>2001-12-31T12:00:00</Timestamp>
  </SourceDetails>
  <AsOfDate>2001-01-01</AsOfDate>
  <Instrument>
    <ASXExchangeSecurityIdentifier>ASX</ASXExchangeSecurityIdentifier>
  </Instrument>
  <Rate>0.0</Rate>

我正在比较的第二个 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<SourceDetails>
        <Origin>FEED</Origin>
        <Identifier>IR</Identifier>
        <Timestamp>2017-01-01T02:11:01Z</Timestamp>
    </SourceDetails>
    <AsOfDate>2017-01-02</AsOfDate>
    <Instrument>
        <CommonCode>GB0</CommonCode>
    </Instrument>
    <Rate>0.69</Rate>

您可以使用 nokogiri-diff gem 来执行此操作。它只是找到差异和 returns 一个 Enumerable 对象。

require 'nokogiri/diff'

xmlDoc1 = File.open("docOne.xml") { |f| Nokogiri::XML(f) }
xmlDoc2 = File.open("docTwo.xml") { |f| Nokogiri::XML(f) }

xmlDoc1.diff(xmlDoc2).each do |diff|
  puts diff
end
#2nd example
doc1 = Nokogiri::XML("<root><aliens><alien><name>Alf</name></alien></aliens></root>")
doc2 = Nokogiri::XML("<root><alienz><alien><name>Alf</name></alien></alienz></root><test></test>")

xmlDoc1.diff(xmlDoc2).each do |diff|
  puts diff
end
#2nd example output
<root>
  <aliens>
    <alien>
      <name>Alf</name>
    </alien>
  </aliens>
</root>
-
<aliens>
  <alien>
    <name>Alf</name>
  </alien>
</aliens>
+
<alienz>
  <alien>
    <name>Alf</name>
  </alien>
</alienz>

使用 Diffy 进行比较的替代解决方案。这是一个扁平字符串比较,但它确实有一个 html 格式的输出。

require 'diffy'

puts Diffy::Diff.new('./docOne.xml', './docTwo.xml', :source => 'files').to_s(:html)
#Example output
<div class="diff">
  <ul>
    <li class="unchanged"><span>&lt;root&gt;</span></li>
    <li class="del"><del>test</del></li>
    <li class="unchanged"><span>&lt;foo&gt;&lt;/foo&gt;</span></li>
    <li class="ins"><ins>&lt;bar&gt;&lt;/bar&gt;</ins></li>
    <li class="unchanged"><span>&lt;/root&gt;</span></li>
  </ul>
</div>