File: rexml/light/node.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: REXML#12
  module: Light#13
  class: Node#17
inherits from
  Object ( Builtin-Module )
has properties
constant: NAMESPLIT #18
constant: PARENTS #19
method: initialize #21
method: size #36
method: each / 1 #44
method: name #48
method: name= / 2 #52
method: parent= / 1 #58
method: local_name #62
method: local_name= / 1 #67
method: prefix / 1 #71
method: namespace / 1 #75
method: namespace= / 1 #79
method: [] / 2 #86
method: =~ / 1 #98
method: []= / 3 #103
method: << #122
method: node_type #133
method: text= / 1 #137
method: root #142
method: has_name? / 2 #147
method: children #151
method: parent #155
method: to_s #159
method: namesplit #165
method: namespace_of / 2 #172
method: prefix_of / 2 #184

Class Hierarchy

Object ( Builtin-Module )
  Node ( REXML::Light ) #17

Code

   1  require 'rexml/xmltokens'
   2  require 'rexml/light/node'
   3 
   4  # [ :element, parent, name, attributes, children* ]
   5    # a = Node.new
   6    # a << "B"    # => <a>B</a>
   7    # a.b     # => <a>B<b/></a>
   8    # a.b[1]      # => <a>B<b/><b/><a>
   9    # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
  10    # a.b[0].c    # => <a>B<b><c/></b><b x="y"/></a>
  11    # a.b.c << "D"    # => <a>B<b><c>D</c></b><b x="y"/></a>
  12  module REXML
  13    module Light
  14      # Represents a tagged XML element.  Elements are characterized by
  15      # having children, attributes, and names, and can themselves be
  16      # children.
  17      class Node
  18        NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
  19        PARENTS = [ :element, :document, :doctype ]
  20        # Create a new element.
  21        def initialize node=nil
  22          @node = node
  23          if node.kind_of? String
  24            node = [ :text, node ]
  25          elsif node.nil?
  26            node = [ :document, nil, nil ]
  27          elsif node[0] == :start_element
  28            node[0] = :element
  29          elsif node[0] == :start_doctype
  30            node[0] = :doctype
  31          elsif node[0] == :start_document
  32            node[0] = :document
  33          end
  34        end
  35 
  36        def size
  37          if PARENTS.include? @node[0]
  38            @node[-1].size
  39          else
  40            0
  41          end
  42        end
  43 
  44        def each( &block )
  45          size.times { |x| yield( at(x+4) ) }
  46        end
  47 
  48        def name
  49          at(2)
  50        end
  51 
  52        def name=( name_str, ns=nil )
  53          pfx = ''
  54          pfx = "#{prefix(ns)}:" if ns
  55          _old_put(2, "#{pfx}#{name_str}")
  56        end
  57 
  58        def parent=( node )
  59          _old_put(1,node)
  60        end
  61 
  62        def local_name
  63          namesplit
  64          @name
  65        end
  66 
  67        def local_name=( name_str )
  68          _old_put( 1, "#@prefix:#{name_str}" )
  69        end
  70 
  71        def prefix( namespace=nil )
  72          prefix_of( self, namespace )
  73        end
  74 
  75        def namespace( prefix=prefix() )
  76          namespace_of( self, prefix )
  77        end
  78 
  79        def namespace=( namespace )
  80          @prefix = prefix( namespace )
  81          pfx = ''
  82          pfx = "#@prefix:" if @prefix.size > 0
  83          _old_put(1, "#{pfx}#@name")
  84        end
  85 
  86        def []( reference, ns=nil )
  87          if reference.kind_of? String
  88            pfx = ''
  89            pfx = "#{prefix(ns)}:" if ns
  90            at(3)["#{pfx}#{reference}"]
  91          elsif reference.kind_of? Range
  92            _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
  93          else
  94            _old_get( 4+reference )
  95          end
  96        end
  97 
  98        def =~( path )
  99          XPath.match( self, path )
 100        end
 101 
 102        # Doesn't handle namespaces yet
 103        def []=( reference, ns, value=nil )
 104          if reference.kind_of? String
 105            value = ns unless value
 106            at( 3 )[reference] = value
 107          elsif reference.kind_of? Range
 108            _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
 109          else
 110            if value
 111              _old_put( 4+reference, ns, value )
 112            else
 113              _old_put( 4+reference, ns )
 114            end
 115          end
 116        end
 117 
 118        # Append a child to this element, optionally under a provided namespace.
 119        # The namespace argument is ignored if the element argument is an Element
 120        # object.  Otherwise, the element argument is a string, the namespace (if
 121        # provided) is the namespace the element is created in.
 122        def << element
 123          if node_type() == :text
 124            at(-1) << element
 125          else
 126            newnode = Node.new( element )
 127            newnode.parent = self
 128            self.push( newnode )
 129          end
 130          at(-1)
 131        end
 132 
 133        def node_type
 134          _old_get(0)
 135        end
 136 
 137        def text=( foo )
 138          replace = at(4).kind_of?(String)? 1 : 0
 139          self._old_put(4,replace, normalizefoo)
 140        end
 141 
 142        def root
 143          context = self
 144          context = context.at(1) while context.at(1)
 145        end
 146 
 147        def has_name?( name, namespace = '' )
 148          at(3) == name and namespace() == namespace
 149        end
 150 
 151        def children
 152          self
 153        end
 154 
 155        def parent
 156          at(1)
 157        end
 158 
 159        def to_s
 160 
 161        end
 162 
 163        private
 164 
 165        def namesplit
 166          return if @name.defined?
 167          at(2) =~ NAMESPLIT
 168          @prefix = '' || $1
 169          @name = $2
 170        end
 171 
 172        def namespace_of( node, prefix=nil )
 173          if not prefix
 174            name = at(2)
 175            name =~ NAMESPLIT
 176            prefix = $1
 177          end
 178          to_find = 'xmlns'
 179          to_find = "xmlns:#{prefix}" if not prefix.nil?
 180          ns = at(3)[ to_find ]
 181          ns ? ns : namespace_of( @node[0], prefix )
 182        end
 183 
 184        def prefix_of( node, namespace=nil )
 185          if not namespace
 186            name = node.name
 187            name =~ NAMESPLIT
 188            $1
 189          else
 190            ns = at(3).find { |k,v| v == namespace }
 191            ns ? ns : prefix_of( node.parent, namespace )
 192          end
 193        end
 194      end
 195    end
 196  end