Class XTemplate::XNode
In: lib/xtemplate/node.rb
lib/xtemplate/yaml.rb
Parent: Object

Methods

Included Modules

XPath Util

Constants

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

Attributes

alt  [RW] 
attrs  [RW] 
children  [RW] 
data_path  [RW] 
name  [RW] 
option  [RW] 
parent  [RW] 
pi  [RW] 
propagation  [RW] 

Public Class methods

[Source]

# 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

[Source]

# File lib/xtemplate/node.rb, line 567
    def XNode.use_default_expand()
      XNode.class_eval(EXPAND_CODE)
    end

[Source]

# 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

Public Instance methods

[Source]

# File lib/xtemplate/node.rb, line 46
    def add_attr(attr)
      @attrs.push([attr,SanitizedString.new("")])
    end

[Source]

# File lib/xtemplate/node.rb, line 54
    def add_attrval(val)
      @attrs[-1][1].concat(sanitize(val))
    end

[Source]

# 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
attrval(key)

Alias for lattrval

also implemented in xt.c.

[Source]

# 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.

[Source]

# 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

[Source]

# 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

[Source]

# 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

[Source]

# 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

[Source]

# File lib/xtemplate/node.rb, line 186
    def lattrval(key)
      @attrs.each{|attr,val|
        if( attr == key )
          return val
        end
      }
      nil
    end

[Source]

# 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

[Source]

# File lib/xtemplate/node.rb, line 196
    def rattrval(key)
      @attrs.reverse.each{|attr,val|
        if( attr == key )
          return val
        end
      }
      nil
    end

[Source]

# File lib/xtemplate/node.rb, line 50
    def set_propagation(flag)
      @propagation = flag
    end

[Source]

# 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

[Source]

# 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

[Source]

# File lib/xtemplate/node.rb, line 58
    def to_s
      s = ""
      dump(s)
      SanitizedString.new(s)
    end

[Source]

# File lib/xtemplate/yaml.rb, line 20
    def to_yaml
      node = deep_dup()
      node.strip!
      node.to_hash(Array,true).to_yaml()
    end

[Validate]