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