XML比较。

最近帮别人写了一个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,不过能凑合用,由于时间跟观众太少的关系,就不解释了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值