require 'net/http'
require 'rexml/document'
module XmlUtils
BASIC_HEADER = ''
def self.get_url_root(url)
xml = Net::HTTP.get(URI(url))
return nil if !xml
xdoc = REXML::Document.new(xml)
return nil if !xdoc
root = xdoc.root
end
def self.get_xml_root(xml)
xdoc = REXML::Document.new(xml)
return nil if !xdoc
root = xdoc.root
end
def self.get_file_root(aFilename)
get_xml_root(MiscUtils.string_from_file(aFilename))
end
def self.single_node(node,xpath,default=nil)
return default if node.nil? || xpath.nil? || xpath==''
val = REXML::XPath.first(node,xpath)
return val.nil? ? default : val
end
def self.peek_node(node,xpath,default=nil)
return default if node.nil? || xpath.nil? || xpath==''
val = REXML::XPath.first(node,xpath)
return val.nil? ? default : val.to_s
end
def self.peek_node_value(node,xpath,default=nil)
peek_node(node,xpath+'/text()',default)
end
# convert onetwo to {'a' => 'one', 'b' => 'two'}
def self.hash_from_elements(aXMLRoot)
result = {}
aXMLRoot.elements.each{|e| result[e.name] = e.text}
return result
end
# given 'textblah' returns {:name=>"tag", :text=>"textblah", "a"=>"1", "b"=>"2"}
def self.hash_from_tag(aTagString)
result = {}
tag = get_xml_root(aTagString)
return nil if !tag
tag.attributes.each_attribute {|attr| result[attr.expanded_name] = attr.value }
result[:name] = tag.name
result[:text] = tag.text if tag.text
return result
end
# given {:name=>"tag", :text=>"textblah", "a"=>"1", "b"=>"2"} returns 'textblah'
def self.tag_from_hash(aHash,aName=nil,aText=nil)
aName ||= aHash[:name]
aText ||= aHash[:text]
result = "<#{aName}"
aHash.each {|k,v| result += " #{k}=\"#{encode(v.to_s)}\"" if k.is_a? String}
result += aText ? " >#{aText}#{aName}>" : " />"
end
def self.hash_to_xml(aHash,aRootName,aDocHeader=true)
xdoc = REXML::Document.new(BASIC_HEADER)
root = xdoc.add_element(aRootName)
aHash.each do |n,v|
root.add_element(n).add_text(v)
end
return xdoc
end
def self.read_simple_items(aRoot,aParentXPath)
result = {}
REXML::XPath.each(aRoot, aParentXPath+'/Item') do |item|
result[item.attribute('Name').to_s] = item.text
end
return result
end
def self.quick_write_simple_items(aHash,aParent)
return "<#{aParent} />\n" if !aHash || aHash.empty?
result = "<#{aParent}>\n"
aHash.each {|key,value| result += "\t- #{value.to_s}
\n" }
result += "<#{aParent}/>\n"
return result
end
def self.read_config_values(aXmlConfig)
xmlRoot = get_file_root(aXmlConfig)
return read_simple_items(xmlRoot,'/Config/SimpleItems')
end
# Takes a node or xml string and writes it out formatted nicely.
# aOutput may be given eg. a stream or nil can be given to get a returned string
def self.format_nicely(aXml,aOutput=nil)
aXml = REXML::Document.new(aXml) unless aXml.is_a?(REXML::Element)
f = REXML::Formatters::Pretty.new(2,true)
f.compact = true
f.width = 120
aOutput ||= ''
f.write(aXml,aOutput)
return aOutput
end
def self.encode(aString)
result = aString.clone;
result.gsub!('&','&')
result.gsub!('<','<')
result.gsub!('>','>')
result.gsub!('"','"')
result.gsub!("'",''')
result.gsub!(/[\x80-\xFF]/) {|c| "#{'%X' % c[0]};"}
return result
end
def self.hash_to_deflist(aHash,aBuilder=nil)
aBuilder ||= Builder::XmlMarkup.new(:indent => 2)
aBuilder.dl do
aHash.each do |k,v|
aBuilder.dt(k.to_s)
aBuilder.dd(v.to_s)
end
end
end
def self.data_to_table(aRowHashes,aCaption=nil,aColNames=nil,aBuilder=nil)
aBuilder ||= Builder::XmlMarkup.new(:indent => 2)
aBuilder.table do
if aCaption.is_a? String
aBuilder.caption(aCaption)
elsif aCaption.is_a? Hash
aBuilder.caption do
XmlUtils.hash_to_deflist(aCaption,aBuilder)
end
end
aColNames ||= aRowHashes.first.keys
aBuilder.thead do
aBuilder.tr do
aColNames.each do |name|
aBuilder.td(name.to_s)
end
end
end
aBuilder.tbody do
aRowHashes.each do |row|
aBuilder.tr do
aColNames.each do |name|
aBuilder.td(row[name].to_s)
end
end
end
end
end
end
end