Class | XTemplate::XNode |
In: |
lib/xtemplate/node.rb
lib/xtemplate/yaml.rb |
Parent: | Object |
DEFAULT_COMMAND | = | { :select => true, :template => true, :element => true, :attribute => true, :expand => true, :include => true, :copy_of => true, :value_of => true, :each => true, :property => true, :invoke => true, :@id => true, :@each => true, :@type => true, } | ||
EXPAND_CODE | = | %q` def expand(data, pdata, rdata, plugin) if( @alt && plugin._alt_exist?(@alt) ) @parent.children.delete(self) end if( @data_path ) case data when Hash val = value_by_path2(@data_path, data, pdata, rdata, plugin) case val when Array nodes = val.collect{|v| node = deep_dup() node.parent = self case v when Hash node.expand_with_hash(v, pdata, rdata, plugin) else node.add_child(v) end node.expand_attr(v) node } @name = nil @attrs = [] @children = nodes #@data_path = nil when Hash expand_attr(val) expand_with_hash(val, pdata, rdata, plugin) else expand_attr(val) add_child(val) end if( @expand ) @name = nil @attrs = [] case val when Hash val.clear() val[TextNode] = self.to_s() if( @expand == :strip ) val[TextNode] = val[TextNode].strip() end when Array for i in 0..(val.size-1) s = @children[i].to_s() if( @expand == :strip ) s = s.strip() end case val[i] when Hash val[i].clear() val[i][TextNode] = s when String val[i][0..-1] = @children[i].to_s() end end when String s = self.to_s() if( @expand == :strip ) s = s.strip() end val[0..-1] = s end @children = [] end end else expand_attr(data) expand_children(data, pdata, rdata, plugin) end # expand <xx:attribute ..> after expanding children. if( @exattr ) val = to_s() @children = [] node = self while( node = node.parent ) if( node.name ) break end end node.add_attr(@exattr) node.add_attrval(val) @exattr = nil end end ` | (1)current data (2)parent data (3)root data (4)plugin object |
alt | [RW] | |
attrs | [RW] | |
children | [RW] | |
data_path | [RW] | |
name | [RW] | |
option | [RW] | |
parent | [RW] | |
pi | [RW] | |
propagation | [RW] |
# File lib/xtemplate/node.rb, line 16 def initialize(name = nil, attrs = nil, children = nil, parent = nil, data_path = nil, propagation = true, exname = nil, exattr = nil, expand = nil, alt = nil, opt={}) @name = name @attrs = attrs || [] @children = children || [] @parent = parent @data_path = data_path @exname = exname @exattr = exattr @expand = expand # :normal, :strip @alt = alt @option = opt if( propagation.nil? ) @propagation = true else @propagation = propagation end end
# File lib/xtemplate/node.rb, line 567 def XNode.use_default_expand() XNode.class_eval(EXPAND_CODE) end
# File lib/xtemplate/node.rb, line 571 def XNode.use_simple_expand() code = EXPAND_CODE.sub(/value_by_path2\(@data_path, data, pdata, rdata, plugin\)/, "data[@data_path]") XNode.class_eval(code) end
# File lib/xtemplate/node.rb, line 46 def add_attr(attr) @attrs.push([attr,SanitizedString.new("")]) end
# File lib/xtemplate/node.rb, line 36 def add_child(node) case node when XNode node.parent = self else node = sanitize(node.to_s) end @children.push(node) end
also implemented in xt.c.
# File lib/xtemplate/node.rb, line 95 def deep_dup(p = nil) node = XNode.new(@name && @name.dup, @attrs && @attrs.dup, nil, p, @data_path && @data_path.dup, @propagation, @exname && @exname.dup, @exattr && @exattr.dup, @expand, @alt, @option.dup) node.children = @children.collect{|child| if( child.is_a?(XNode) ) child.deep_dup(node) else child end } node end
also implemented in xt.c.
# File lib/xtemplate/node.rb, line 65 def dump(io) if( @name ) attrs = @attrs.collect{|a,val| "#{a}=\"#{val}\"" } if( attrs.size > 0 ) attrs = " " + attrs.join(" ") else attrs = "" end if( @children.empty? ) # experimental io << "<#{@name}#{attrs} />" return io else io << "<#{@name}#{attrs}>" end # io << "<#{@name}#{attrs}>" end for s in @children if( s.is_a?(XNode) ) s.dump(io) else io << s end end if( @name ) io << "</#{@name}>" end io end
# File lib/xtemplate/node.rb, line 398 def expand_attr(data) # substituting attribute values. @attrs = ([[nil,@exname],[nil,@exattr]]+@attrs).collect{|attr,val| [ attr, if( val ) val.gsub(/(@@?)[\{\(](.+?)[\}\)]/){|str| at = $1 key = $2 case at.size when 1 if( data.is_a?(Hash) ) v = data[key] case v when Hash str = v[TextNode] || '' else str = v.to_s end else str = '' end when 2 str[0,1] = '' end sanitize(str) } else nil end ] } @exname = @attrs.shift()[1] @exattr = @attrs.shift()[1] if( @exname ) @name = @exname @exname = nil end end
# File lib/xtemplate/node.rb, line 438 def expand_children(data, pdata, rdata, plugin) for child in @children if( child.is_a?(XNode) ) child.expand(data, pdata, rdata, plugin) end end end
# File lib/xtemplate/node.rb, line 446 def expand_with_hash(data, pdata, rdata, plugin) # insert attributes and elements specified by ID. for key,attrval in data if( key == TextNode ) if( attrval ) @children = [] add_child(attrval) end elsif( key[0] == ?@ ) attr = key[1..-1] if( @name ) add_attr(attr) add_attrval(attrval) elsif( @propagation ) node = @parent while( node ) if( node.name ) node.add_attr(attr) node.add_attrval(attrval) break end node = node.parent end end end end expand_children(data, pdata, rdata, plugin) end
# File lib/xtemplate/node.rb, line 186 def lattrval(key) @attrs.each{|attr,val| if( attr == key ) return val end } nil end
# File lib/xtemplate/node.rb, line 221 def prepare(xmlns = nil, enable = nil, templates = nil) # find xmlns:xxx="..." enable ||= DEFAULT_COMMAND templates ||= {} tmp = [] @attrs.each_with_index{|elem,idx| attr,val, = elem if( (attr =~ /^xmlns:(.+)/) && (val == BIND_URI) ) xmlns = $1 @attrs.delete_at(idx) break end } if( @name ) if( xmlns ) if( @name =~ /#{xmlns}:(.+)/ ) # special tags cmd = $1.tr('-','_').intern if( enable[cmd] ) case cmd when :template t_name = attrval("name") || attrval("#{xmlns}:name") @name = nil @attrs = [] if( t_name ) templates[t_name] = self end when :expand @name = nil @data_path = attrval("id") || attrval("#{xmlns}:id") with_strip = attrval("strip") || attrval("#{xmlns}:strip") case with_strip when "yes" @expand = :strip else @expand = :normal end when :select, :value_of @name = nil @data_path = attrval("id") || attrval("#{xmlns}:id") if( @propagation = attrval("propagation") || attrval("#{xmlns}:propagation") ) @propagation = (@propagation == "yes") end when :copy_of @name = nil @data_path = attrval("id") || attrval("#{xmlns}:id") with_tag = attrval("with") || attrval("#{xmlns}:with") || '' if( @data_path ) @data_path = @data_path + "{dump(#{with_tag})}" end if( @propagation = attrval("propagation") || attrval("#{xmlns}:propagation") ) @propagation = (@propagation == "yes") end when :each @name = nil @data_path = attrval("id") || attrval("#{xmlns}:id") if( @data_path ) @data_path = @data_path + "{array()}" end when :element @exname = attrval("name") || attrval("#{xmlns}:name") @data_path = attrval("id") || attrval("#{xmlns}:id") @name = nil @attrs = [] when :attribute @name = nil @exattr = attrval("name") || attrval("#{xmlns}:name") @data_path = attrval("id") || attrval("#{xmlns}:id") when :property, :invoke @name = nil @data_path = attrval("id") || attrval("#{xmlns}:id") @data_path += "." @data_path += attrval("name") || attrval("#{xmlns}:name") || attrval("method") || attrval("#{xmlns}:method") withval = attrval("with") || attrval("#{xmlns}:with") || '' if( withval ) @data_path += "(#{withval})" end when :import src = attrval("src") || attrval("#{xmlns}:src") @data_path = "{data(#{src})}" @name = nil when :include src = attrval("src") || attrval("#{xmlns}:src") case src when /^\$(.+)/ doc = eval(src) when /^file:\/\/(.+)/ doc = File.open($1){|file| file.read } when /^http:\/\/(.+)/ raise(NotImplementedError, "'#{src}' can not be included.") else doc = File.open(src){|file| file.read } end parser = XMLParser.new() node = parser.parse(doc) node.prepare(xmlns, enable, templates) @name = nil add_child(node) else raise(NotImplementedError, "'#{cmd.tr("_","-").to_s}' is not supported.") end if( @alt = (attrval("alt") || attrval("#{xmlns}:id")) ) @data_path += "{alt(#{@alt})}" end else raise(RuntimeError, "'#{cmd.tr("_","-").to_s}' is invalid.") end else # parse attribute with xmlns tmp = [] attr_id = "#{xmlns}:id" attr_type = "#{xmlns}:type" attr_each = "#{xmlns}:each" attr_alt = "#{xmlns}:alt" @attrs.each{|attr,val| case attr when attr_id if( enable[:@id] ) @data_path = val else raise(RuntimeError, "'#{attr}' is invalid.") end when attr_each if( enable[:@each] ) @data_path = val + "{array()}" else raise(RuntimeError, "'#{attr}' is invalid.") end when attr_type if( enable[:@type] ) @option[:type] = val else raise(RuntimeError, "'#{attr}' is invalid.") end when attr_alt @alt = val else tmp.push([attr,val]) end } if( @alt ) @data_path += "{alt(#{@alt})}" end @attrs = tmp end else # xmlns # parse attribute tmp = [] @attrs.each{|attr,val| case attr when 'id' if( enable[:@id] ) @data_path = val else tmp.push([attr,val]) end when 'each' if( enable[:@each] ) @data_path = @data_path + "{array()}" else tmp.push([attr,val]) end else tmp.push([attr,val]) end } @attrs = tmp end end @children.each{|child| if( child.is_a?(XNode) ) child.prepare(xmlns, enable, templates) end } end
# File lib/xtemplate/node.rb, line 196 def rattrval(key) @attrs.reverse.each{|attr,val| if( attr == key ) return val end } nil end
# File lib/xtemplate/node.rb, line 113 def strip!(recursive=true) @children.reject!{|child| child.is_a?(String) && child =~ /\A\s*\z/ } if( recursive ) @children.each{|child| if( child.is_a?(XNode) ) child.strip!(true) end } end end
# File lib/xtemplate/node.rb, line 124 def to_hash(array = XArray, unsanitize_p = false) if( @hash ) return @hash end ary = array[] @children.each{|child| if( child.is_a?(XNode) ) ary.push(child.to_hash(array,unsanitize_p)) else text = child.to_s if( ary[-1].is_a?(String) ) ary[-1].concat(text) else if( unsanitize_p ) text = unsanitize(text) end ary.push(text.dup) end end } @attrs.each{|attr,val| if( unsanitize_p ) val = unsanitize(val) end ary.push({'@'+attr => val}) } if( ary.size == 1 ) ary = ary[0] end case @option[:type] when 'array' ary = Array[*ary] when 'hash' ary = eval_action("hash()", ary, nil) when 'int' ary = ary.to_i when 'float' ary = ary.to_f when 'string' ary = ary.to_s end if( @name ) @hash = {@name => ary} else case ary when Hash @hash = ary else @hash = {} ary.each{|h| if( h.is_a?(Hash) ) h.each{|key,val| @hash[key] = val } end } end end @hash end