# -*- ruby -*- # # XTemplate # require 'xtemplate/util' require 'xtemplate/xpath' require 'xtemplate/node' require 'xtemplate/xml' begin require 'xtemplate_ext' rescue LoadError end module XTemplate def warn(*msg) $stderr.puts(msg.join) end class XMLTemplate attr_reader :node protected :node def initialize(doc, templates = nil) case doc when XNode @node = doc @templates = templates || {} else parser = XMLParser.new @node = parser.parse(doc) @templates = templates || {} @node.prepare(nil, nil, @templates) end end def dup() self.class.new(@node.deep_dup, @templates) end alias clone dup def [](name) node = @templates[name] if( node ) self.class.new(node) else nil end end def []=(name, template) node = @templates[name] node.children = [] if( template ) [template.node.children].flatten.each{|child| node.add_child(child) } end node end def <<(template) @node.add_child(template.node) self end def to_s @node.to_s end def dump() [Marshal.dump(self)].pack("m") end def XMLTemplate.load(str) if( str.respond_to?(:read) ) str = str.read end Marshal.load(str.unpack("m")[0]) end DEFAULT_OPTS = { :keep_template => true, :keep_data => false, :plugin => XPath::Action.new, } def expand(data, opts = nil) s = SanitizedString[''] expand2(s, data, opts) s end def expand2(io, data, opts = nil) if( opts ) DEFAULT_OPTS.each{|key,val| opts[key] ||= val } else opts = DEFAULT_OPTS end if( opts[:keep_template] ) node = @node.deep_dup() else node = @node end if( opts[:keep_data] ) data = XTemplate::dup_data(data) end if( defined?(data.to_hash) ) data = data.to_hash end node.expand(data, nil, data, opts[:plugin]) # (1)current data (2)parent data (3)root data node.dump(io) end end module_function def use_simple_expand() XNode::use_simple_expand() end def use_default_expand() XNode::use_default_expand() end def use_simple_xpath() XPath::use_simple_xpath() end def use_default_xpath() XPath::use_default_xpath() end def dup_data(data, oids=[]) if( oids.include?(data.id) ) data else oids.push(data.id) case data when Hash data = data.dup data.each{|key,val| data[key] = dup_data(val,oids)} data when Array data = data.dup data.collect!{|val| dup_data(val,oids) } data # when Numeric, TrueClass, FalseClass # immutable objects # data else begin data.dup rescue TypeError data end end end end EscapedString = SanitizedString Template = XMLTemplate TextNode = XPath::TextNode end