最近帮别人写了一个XML的比较的小程序,分享一下
module XMLTool
class Node
attr_reader :nodes, :name, :text, :attributes
def initialize name, text, attributes = {}, ancestor_nodes = []
@name = name
@attributes = attributes
@text = text
@ancestor_nodes = ancestor_nodes.clone
@nodes ||= {}
end
def ancestor_nodes
@ancestor_nodes.clone
end
def add_node node
@nodes[node.name] ||= []
@nodes[node.name] << node
end
# blk params: node name, node array
def each &blk
@nodes.each &blk
end
def has_children?
!@nodes.empty?
end
def compare_with a_node, failed_nodes = [], passed_nodes = []#, *ignore_nodes
#puts "Current Node: #{self.name}, Compared Node: #{a_node.name}"
#failed_nodes = failed_nodes.clone
pass_fg = true
if has_children?
if a_node.has_children?
each do |name, children_nodes|
if a_node.nodes[name].nil?
#puts "Not Found. Node: #{name}, #{attributes}, #{text}"
pass_fg = false
break
else
children_nodes.each do |child_node|
ps_fg = false
a_node.nodes[name].each do |a_child|
if child_node.attributes == a_child.attributes
if child_node.compare_with(a_child, failed_nodes, passed_nodes)[0]
ps_fg = true
break
end
end
end
if ps_fg
next
else
pass_fg = false
break
end
end
end
end
#puts "Not Found. Node: #{name}, #{attributes}, #{text}" if !pass_fg
else
# "Structure Error."
pass_fg = false
end
else
if a_node.has_children?
# "Structure Error: Node :#{name}, #{a_node.name}"
pass_fg = false
else
if a_node.name != name || a_node.attributes != attributes || a_node.text != text
#puts %Q{Node Error:
#Node Name:#{name}, #{a_node.name}
#Attributes: #{attributes}, #{a_node.attributes}
#Value: #{text}, #{a_node.text}
#}
pass_fg = false
end
end
end
#puts error_msg.join("\n") if !error_msg.empty?
if pass_fg
#puts self.name
passed_nodes << self
failed_nodes.delete(self) if failed_nodes.include?(self)
else
failed_nodes << self if !passed_nodes.include? (self)
end
return([pass_fg, failed_nodes])
end
end
end
module XMLTool
class Tree
attr_reader :root
def initialize xml_file
require 'rexml/document'
File.open(xml_file) do |file|
doc = REXML::Document.new(file)
@root = parse_xml(doc.root, Node.new(doc.root.name, doc.root.text, doc.root.attributes))
end
end
def compare_with another_tree, *ignore_nodes
end
def self.filter_failed_nodes failed_nodes
rets = []
failed_nodes.each do |node|
ancestor_chain = node.ancestor_nodes << node
rets << ancestor_chain if rets.empty?
rets.each do |ret|
if (ret & ancestor_chain) == ret
rets.delete ret
rets << ancestor_chain
else
if (ret & ancestor_chain) != ancestor_chain
rets << ancestor_chain
end
end
end
end
return rets
end
private
# Fill Node according element
def parse_xml element, node
#puts element.name
#puts node.ancestor_nodes
if element.has_elements?
element.elements.each do |sub_ele|
ancestor_nodes = node.ancestor_nodes << node
if sub_ele.has_elements?
child_node = Node.new(sub_ele.name, sub_ele.text, sub_ele.attributes, ancestor_nodes)
node.add_node(parse_xml(sub_ele, child_node))
else
node.add_node(Node.new(sub_ele.name, sub_ele.text, sub_ele.attributes, ancestor_nodes))
end
end
end
node
end
end
end
测试代码
$LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include? File.dirname(__FILE__)
require 'xmltool'
include XMLTool
root1 = Tree.new('Completion090_MsgValue_XML.xml').root
root2 = Tree.new('Completion090_MsgValue_XML5.xml').root
#tree.nodes[0].nodes[0].nodes[0].nodes.each do |e|
# puts e.tag_name
# puts e.text
#end
ret = root1.compare_with(root2)
#ret = root2.compare_with(root1)
puts ret[0]
Tree.filter_failed_nodes(ret[1]).each do |ancestor_chain|
ancestor_chain.each_with_index do |node, i|
puts "#{"\s" * 2 * i}#{node.name} #{node.attributes} ->"
end
puts ancestor_chain.last.text
puts "------------------"
end
#puts ret[1][0].name
#puts ret[1][0].attributes
#puts ret[1][1].name
#puts ret[1][1].attributes
之前都没做过XML的东西,nokogiri看了一下不会用,就用rexml解析xml,目前可能还有点bug,不过能凑合用,由于时间跟观众太少的关系,就不解释了。
分享到:
相关推荐
JSON 和 XML 比较 JSON 和 XML 是两种常用的数据交换格式,它们之间有很多相似之处,也有许多不同之处。下面我们将从多方面对比 JSON 和 XML。 可读性和可扩展性 JSON 和 XML 都是文本表示的数据格式,可以跨平台...
在"java中四种操作xml方式的比较.txt"文件中,你可能会找到关于这四种方法的详细比较,包括它们的实现代码示例、性能测试结果以及各种情况下如何选择最佳方法的建议。而"www.pudn.com.txt"文件可能是下载来源或附加...
xmlunit1.6 官网下载的 xml比较是否相同的jar 包,xmlunit1.6 官网下载的 xml比较是否相同的jar 包
Eclipse的版本控制插件可以方便地比较代码文件的差异,而XML比较器则专门针对XML格式的数据进行高效比较。 “解压就可用”表明这是一个可直接运行的压缩包,无需安装,用户只需下载并解压缩后即可开始使用。这为...
XML(eXtensible Markup Language)是一种通用的文本格式,被广泛运用于数据交换和数据存储(虽然近年来 JSON 盛行,大有取代 XML 的趋势,但是对于一些已有系统和架构,比如 WebService,由于历史原因,仍旧会继续...
2. **XML比较**:比较两个XML文件,主要对比它们的节点结构和值。可以遍历每个文件的根节点,然后递归地比较子节点。节点的比较包括节点名、属性、文本内容等。如果两个文件的节点结构相同,但值不同,则可能发生了...
ExamXML Pro是一款专门用于XML/CSV文档的比较工具,可视化的操作方式使用起来更简单,能够以树形结构来显示XML文档,能够从任何数据源中读取并进行比较,另外还可以合并XML文档,比较SQL SERVER数据以及网页等。...
7. **XML比较**:提供文档差异比较功能,方便用户检查和合并不同版本的XML文档。 8. **XML预览**:实时预览XML文档,以便于理解和调整文档格式。 二、Oxygen XML Editor 17.0新特性 17.0版本可能包含以下改进或...
ExamXML 一款可视化的XML文档比较工具,可用于比较XML、CSV文档,合并XML文档,读取和比较SQL servers的数据, 网页等等。ExamXML以树状结构显示XML文档,并可以插入、修改XML元素。可直接从FTP或网页上下载文件进行...
8. **其他特性**:还包括XML与JSON互转、SOAP接口测试、XML比较、XML编码和解码等功能,进一步增强了XML处理的全面性。 XMLSpy2006因其丰富的功能和友好的用户界面,成为了XML开发者的重要工具。无论是初学者还是...
此外,它还包含了一些实用工具类,如XML比较器,用于验证两个XML文档的结构一致性。 4. **与其他jcommon组件的集成**: 作为jcommon的一部分,jcommon-xml可以无缝集成到使用jcommon其他组件的项目中。这使得...
7. **其他功能**:还包括XML比较、XML地图、图表生成等功能,帮助开发者全面管理和分析XML数据。 在提供的压缩包中,除了XMLSpy 2013的安装文件外,还包含了一个名为"CCleaner.exe"的程序,这通常是CCleaner的安装...
XML(eXtensible Markup Language)是一种用于存储和传输数据的标记语言,它以其结构化、可扩展性和易于解析的特点广泛应用于Web服务、配置...同时,这也可以作为一个起点,根据具体需求进一步定制和扩展XML比较功能。
《XML文档比较工具》(A7Soft ExamXML PRO)v5.15[压缩包]
pugixml是一款轻量级、高性能的C++库,专为XML解析和操作而设计。这个库由Artemev开发,提供了简单易用的API,使得在C++项目中处理XML文档变得非常便捷。本示例将详细介绍如何使用pugixml进行XML的读取和写入操作。 ...
TinyXML和TinyXML2是两个小型的开源库,专门用于解析和操作XML(eXtensible Markup Language)文档。这两个库都是用C++编写的,为C++开发者提供了方便的接口来读取、写入和操作XML数据。下面将详细介绍这两个库的...
每日XML比较可能涉及到以下几个关键知识点: 1. **XML解析**:XML文件需要被解析才能理解其内容。解析器可以是DOM(Document Object Model)解析器,它一次性加载整个XML文档到内存中;或者是SAX(Simple API for ...
使用java工具xml2axml.jar反编译AndroidManafest文件 通过xml2axml.jar工具反编译AndroidManafest文件 还原AndroidManafest.xml详细过程: 1、获取到apk 2、解压获取里面的AndroidManifest.xml文件 3、在xml2axml....
在PowerBuilder(简称PB)这个强大的开发环境中,处理XML文件是一项常见的任务。XML(Extensible Markup Language)是一种用于存储和传输数据的通用格式,尤其在跨平台和网络应用中广泛使用。本示例主要探讨如何在...