vcdom 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/lib/vcdom/attr.rb +70 -0
  2. data/lib/vcdom/attr_node_map.rb +30 -0
  3. data/lib/vcdom/attr_ns.rb +38 -0
  4. data/lib/vcdom/character_data.rb +22 -0
  5. data/lib/vcdom/child.rb +53 -0
  6. data/lib/vcdom/document.rb +126 -0
  7. data/lib/vcdom/element.rb +332 -0
  8. data/lib/vcdom/element_ns.rb +44 -0
  9. data/lib/vcdom/node.rb +278 -0
  10. data/lib/vcdom/node_list.rb +32 -0
  11. data/lib/vcdom/parent.rb +126 -0
  12. data/lib/vcdom/text.rb +23 -0
  13. data/lib/vcdom/xml_parser.rb +368 -0
  14. data/lib/vcdom/xml_serializer.rb +55 -0
  15. metadata +48 -81
  16. data/History.txt +0 -4
  17. data/Manifest.txt +0 -34
  18. data/PostInstall.txt +0 -7
  19. data/README.rdoc +0 -51
  20. data/Rakefile +0 -26
  21. data/lib/vcdom/minidom/attr.rb +0 -139
  22. data/lib/vcdom/minidom/attr_ns.rb +0 -47
  23. data/lib/vcdom/minidom/cdata_section.rb +0 -34
  24. data/lib/vcdom/minidom/character_data.rb +0 -263
  25. data/lib/vcdom/minidom/comment.rb +0 -34
  26. data/lib/vcdom/minidom/document.rb +0 -245
  27. data/lib/vcdom/minidom/dom_exception.rb +0 -51
  28. data/lib/vcdom/minidom/dom_implementation.rb +0 -214
  29. data/lib/vcdom/minidom/element.rb +0 -512
  30. data/lib/vcdom/minidom/element_ns.rb +0 -42
  31. data/lib/vcdom/minidom/mini_parser.rb +0 -9
  32. data/lib/vcdom/minidom/mini_serializer.rb +0 -118
  33. data/lib/vcdom/minidom/minidom_standard_error.rb +0 -9
  34. data/lib/vcdom/minidom/mod_child_node.rb +0 -51
  35. data/lib/vcdom/minidom/mod_elements_getter.rb +0 -49
  36. data/lib/vcdom/minidom/mod_namespaceuri_manageable.rb +0 -152
  37. data/lib/vcdom/minidom/mod_parent_node.rb +0 -307
  38. data/lib/vcdom/minidom/named_node_map_attr.rb +0 -277
  39. data/lib/vcdom/minidom/node.rb +0 -178
  40. data/lib/vcdom/minidom/node_list.rb +0 -41
  41. data/lib/vcdom/minidom/text.rb +0 -77
  42. data/lib/vcdom/minidom/xml_reg_exp.rb +0 -39
  43. data/lib/vcdom/minidom.rb +0 -9
  44. data/lib/vcdom.rb +0 -6
  45. data/script/console +0 -10
  46. data/script/destroy +0 -14
  47. data/script/generate +0 -14
  48. data/test/test_helper.rb +0 -3
  49. data/test/test_vcdom.rb +0 -11
data/lib/vcdom/attr.rb ADDED
@@ -0,0 +1,70 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node"
4
+ require "vcdom/parent"
5
+
6
+ module VCDOM
7
+ class Attr < Node
8
+
9
+ include Parent
10
+
11
+ def initialize( doc, name )
12
+ initialize_parent()
13
+ super( doc )
14
+ @owner_element = nil
15
+ @local_name = name
16
+ end
17
+
18
+ def node_type
19
+ ATTRIBUTE_NODE
20
+ end
21
+
22
+ def owner_element
23
+ @owner_element
24
+ end
25
+ def _set_owner_element( elem )
26
+ @owner_element = elem
27
+ end
28
+
29
+ def name
30
+ @local_name.to_s()
31
+ end
32
+ alias :node_name :name
33
+
34
+ def local_name
35
+ nil
36
+ end
37
+
38
+ def value
39
+ val = String.new()
40
+ self.each_child_node do |n|
41
+ # Text のみを考慮
42
+ val << n.node_value
43
+ end
44
+ return val
45
+ end
46
+ def value=(val)
47
+ while self.first_child do
48
+ self.remove_child( self.first_child )
49
+ end
50
+ self.append_child( self.owner_document.create_text_node( val ) )
51
+ end
52
+
53
+ def append_child( new_child )
54
+ # ノードのタイプチェックなど
55
+ if not new_child.is_a? Node then
56
+ raise ArgumentError.new( "the argument [#{new_child.inspect}] is not an object of the expected class." )
57
+ end
58
+ # Text, EntityReference
59
+ case new_child.node_type
60
+ when TEXT_NODE, ENTITY_REFERENCE_NODE then
61
+ # OK
62
+ else
63
+ # ERROR
64
+ raise "ERROR"
65
+ end
66
+ _append_child( new_child )
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,30 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node"
4
+
5
+ module VCDOM
6
+ class AttrNodeMap #< NamedNodeMap
7
+
8
+ include Enumerable
9
+
10
+ def initialize( nodes )
11
+ @nodes = nodes
12
+ end
13
+ def item( index )
14
+ @nodes[index]
15
+ end
16
+ def length
17
+ @nodes.length
18
+ end
19
+ def each
20
+ @nodes.each do |n|
21
+ yield n
22
+ end
23
+ end
24
+
25
+ def inspect
26
+ "#<VCXML::DOM::AttrNodeMap>"
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,38 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node"
4
+ require "vcdom/attr"
5
+
6
+ module VCDOM
7
+ class AttrNS < Attr
8
+
9
+ def initialize( doc, namespace_uri, prefix, local_name )
10
+ super( doc, local_name )
11
+ @namespace_uri = namespace_uri
12
+ @prefix = prefix
13
+ end
14
+
15
+ def name
16
+ if @prefix then
17
+ "#{@prefix.to_s}:#{@local_name.to_s}"
18
+ else
19
+ @local_name.to_s()
20
+ end
21
+ end
22
+ alias :node_name :name
23
+
24
+ def prefix
25
+ @prefix.nil? ? nil : @prefix.to_s()
26
+ end
27
+ def prefix=(val)
28
+ @prefix = val.nil? ? nil : val.intern
29
+ end
30
+ def local_name
31
+ @local_name.to_s()
32
+ end
33
+ def namespace_uri
34
+ @namespace_uri.nil? ? nil : @namespace_uri.to_s()
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node"
4
+
5
+ module VCDOM
6
+ class CharacterData < Node
7
+
8
+ def initialize( doc, data )
9
+ super( doc )
10
+ @data = data
11
+ end
12
+
13
+ def data
14
+ @data.to_s
15
+ end
16
+ alias :node_value :data
17
+ def length
18
+ @data.to_s.length
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,53 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node_list"
4
+
5
+ module VCDOM
6
+ module Child
7
+
8
+ def initialize_child()
9
+ @parent_node = nil
10
+ @next_sibling = nil
11
+ @prev_sibling = nil
12
+ end
13
+
14
+ def parent_node
15
+ @parent_node
16
+ end
17
+ def _set_parent_node( parent_node )
18
+ @parent_node = parent_node
19
+ end
20
+ def _set_next_sibling( next_node )
21
+ next_node.previous_sibling = self
22
+ next_node.next_sibling = self.next_sibling
23
+ self.next_sibling.previous_sibling = next_node until self.next_sibling.nil?
24
+ self.next_sibling = next_node
25
+ end
26
+ def previous_sibling
27
+ @prev_sibling
28
+ end
29
+ def previous_sibling=(node)
30
+ @prev_sibling = node
31
+ end
32
+ protected :previous_sibling=
33
+ def next_sibling
34
+ @next_sibling
35
+ end
36
+ def next_sibling=(node)
37
+ @next_sibling = node
38
+ end
39
+ protected :next_sibling=
40
+ def _leave_from_tree()
41
+ @parent_node = nil
42
+ if @next_sibling then
43
+ @next_sibling.previous_sibling = @prev_sibling
44
+ @next_sibling = nil
45
+ end
46
+ if @prev_sibling then
47
+ @prev_sibling.next_sibling = @next_sibling
48
+ @prev_sibling = nil
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,126 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node"
4
+ require "vcdom/parent"
5
+ require "vcdom/element"
6
+ require "vcdom/element_ns"
7
+ require "vcdom/attr"
8
+ require "vcdom/attr_ns"
9
+ require "vcdom/text"
10
+
11
+ module VCDOM
12
+ class Document < Node
13
+
14
+ include Parent
15
+
16
+
17
+ def initialize()
18
+ initialize_parent()
19
+ super( nil )
20
+ end
21
+
22
+ def node_type
23
+ DOCUMENT_NODE
24
+ end
25
+
26
+ def append_child( new_child )
27
+ # ノードのタイプチェックなど
28
+ if not new_child.is_a? Node then
29
+ raise ArgumentError.new( "the argument [#{new_child.inspect}] is not an object of the expected class." )
30
+ end
31
+ # Element (maximum of one), ProcessingInstruction, Comment, DocumentType (maximum of one)
32
+ case new_child.node_type
33
+ when ELEMENT_NODE then
34
+ # 既に追加されてるかどうかのチェック
35
+ if @document_element.nil? then
36
+ @document_element = new_child
37
+ else
38
+ raise "HIERARCHY_REQUEST_ERR"
39
+ end
40
+ when DOCUMENT_TYPE_NODE then
41
+ # 既に追加されてるかどうかのチェック
42
+ when PROCESSING_INSTRUCTION_NODE, COMMENT_NODE then
43
+ # OK
44
+ else
45
+ # ERROR
46
+ raise "ERROR"
47
+ end
48
+ _append_child( new_child )
49
+ end
50
+
51
+ def create_element( tag_name )
52
+ elem = nil
53
+ if tag_name.is_a? String then
54
+ elem = Element._new( self, tag_name.intern )
55
+ else
56
+ raise "ERROR"
57
+ end
58
+ elem
59
+ end
60
+
61
+ def create_element_ns( namespace_uri, qualified_name )
62
+ elem = nil
63
+ if namespace_uri.is_a? String then
64
+ namespace_uri = namespace_uri.intern
65
+ elsif not namespace_uri.nil? then
66
+ raise "ERROR"
67
+ end
68
+ if qualified_name.is_a? String then
69
+ name_parts = qualified_name.split /:/
70
+ if name_parts.length == 1 then
71
+ elem = ElementNS._new( self, namespace_uri, nil, name_parts[0].intern )
72
+ elsif name_parts.length == 2 then
73
+ elem = ElementNS._new( self, namespace_uri, name_parts[0].intern, name_parts[1].intern )
74
+ else
75
+ raise "ERROR"
76
+ end
77
+ else
78
+ raise "ERROR"
79
+ end
80
+ elem
81
+ end
82
+
83
+ def create_attribute( name )
84
+ attr = nil
85
+ if name.is_a? String then
86
+ attr = Attr._new( self, name.intern )
87
+ else
88
+ raise ArgumentError.new( "the argument [#{new_child.inspect}] is not an object of the expected class." )
89
+ end
90
+ attr
91
+ end
92
+
93
+ def create_attribute_ns( namespace_uri, qualified_name )
94
+ attr = nil
95
+ if namespace_uri.is_a? String then
96
+ namespace_uri = namespace_uri.intern
97
+ elsif not namespace_uri.nil? then
98
+ raise ArgumentError.new( "the argument *namespace_uri* must be a String object or nil." )
99
+ end
100
+ if qualified_name.is_a? String then
101
+ name_parts = qualified_name.split /:/
102
+ if name_parts.length == 1 then
103
+ attr = AttrNS._new( self, namespace_uri, nil, name_parts[0].intern )
104
+ elsif name_parts.length == 2 then
105
+ attr = AttrNS._new( self, namespace_uri, name_parts[0].intern, name_parts[1].intern )
106
+ else
107
+ raise "ERROR"
108
+ end
109
+ else
110
+ raise "ERROR"
111
+ end
112
+ attr
113
+ end
114
+
115
+ def create_text_node( data )
116
+ node = nil
117
+ if data.is_a? String then
118
+ node = Text._new( self, data.intern )
119
+ else
120
+ raise ArgumentError.new( "the argument [#{data.inspect}] is not an object of the expected class. the class : #{data.class}" )
121
+ end
122
+ node
123
+ end
124
+
125
+ end
126
+ end
@@ -0,0 +1,332 @@
1
+ # coding : utf-8
2
+
3
+ require "vcdom/node"
4
+ require "vcdom/parent"
5
+ require "vcdom/child"
6
+ require "vcdom/attr_node_map"
7
+
8
+ module VCDOM
9
+ class Element < Node
10
+
11
+ include Parent
12
+ include Child
13
+
14
+ def initialize( doc, tag_name )
15
+ initialize_parent()
16
+ super( doc )
17
+ @local_name = tag_name
18
+ # attributes
19
+ @attr_nodes = Array.new()
20
+ @attr_node_map = AttrNodeMap.new( @attr_nodes )
21
+ end
22
+
23
+ def node_type
24
+ ELEMENT_NODE
25
+ end
26
+
27
+ def tag_name
28
+ @local_name.to_s()
29
+ end
30
+ alias :node_name :tag_name
31
+
32
+ def local_name
33
+ nil
34
+ end
35
+
36
+ def append_child( new_child )
37
+ # ノードのタイプチェックなど
38
+ if not new_child.is_a? Node then
39
+ raise ArgumentError.new( "the argument [#{new_child.inspect}] is not an object of the expected class." )
40
+ end
41
+ # Element, Text, Comment, ProcessingInstruction, CDATASection, EntityReference
42
+ case new_child.node_type
43
+ when ELEMENT_NODE, TEXT_NODE, CDATA_SECTION_NODE, ENTITY_REFERENCE_NODE, PROCESSING_INSTRUCTION_NODE, COMMENT_NODE then
44
+ # OK
45
+ else
46
+ # ERROR
47
+ raise "ERROR"
48
+ end
49
+ _append_child( new_child )
50
+ end
51
+
52
+ # attributes
53
+ def attributes
54
+ @attr_node_map
55
+ end
56
+ def each_attr_node
57
+ @attr_nodes.each do |n|
58
+ yield n
59
+ end
60
+ end
61
+
62
+ # setAttributeNode
63
+ # Adds a new attribute node. If an attribute with that name (nodeName) is already present in the element,
64
+ # it is replaced by the new one. Replacing an attribute node by itself has no effect.
65
+ # To add a new attribute node with a qualified name and namespace URI, use the setAttributeNodeNS method.
66
+ # @param new_attr The Attr node to add to the attribute list.
67
+ # @return If the newAttr attribute replaces an existing attribute, the replaced Attr node is returned,
68
+ # otherwise null is returned.
69
+ def set_attribute_node( new_attr )
70
+ if new_attr.owner_document != self.owner_document then
71
+ raise "WRONG_DOCUMENT_ERR"
72
+ end
73
+ if not new_attr.owner_element.nil? then
74
+ raise "INUSE_ATTRIBUTE_ERR"
75
+ end
76
+ old_attr = nil
77
+ @attr_nodes << new_attr
78
+ new_attr._set_owner_element( self )
79
+ old_attr
80
+ end
81
+ def set_attribute( name, value )
82
+ attr = self.owner_document.create_attribute( name )
83
+ attr.append_child( self.owner_document.create_text_node( value ) )
84
+ self.set_attribute_node( attr )
85
+ nil
86
+ end
87
+
88
+ # setAttributeNodeNS introduced in DOM Level 2
89
+ # Adds a new attribute. If an attribute with that local name and that namespace URI is already present in the element, it is replaced by the new one. Replacing an attribute node by itself has no effect.
90
+ # Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to have no namespace.
91
+ # @param new_attr The Attr node to add to the attribute list.
92
+ # @return If the newAttr attribute replaces an existing attribute with the same local name and namespace URI, the replaced Attr node is returned, otherwise null is returned.
93
+ def set_attribute_node_ns( new_attr )
94
+ if new_attr.owner_document != self.owner_document then
95
+ raise "WRONG_DOCUMENT_ERR"
96
+ end
97
+ if not new_attr.owner_element.nil? then
98
+ raise "INUSE_ATTRIBUTE_ERR"
99
+ end
100
+ old_attr = nil
101
+ @attr_nodes << new_attr
102
+ new_attr._set_owner_element( self )
103
+ old_attr
104
+ end
105
+ def set_attribute_ns( namespace_uri, qualified_name, value )
106
+ attr = self.owner_document.create_attribute_ns( namespace_uri, qualified_name )
107
+ attr.append_child( self.owner_document.create_text_node( value ) )
108
+ self.set_attribute_node_ns( attr )
109
+ nil
110
+ end
111
+ def get_attribute_ns( namespace_uri, local_name )
112
+ @attr_nodes.each do |attr|
113
+ if attr.namespace_uri == namespace_uri and attr.local_name == local_name then
114
+ #//////////////////////////
115
+ # 変更する
116
+ #//////////////////////////
117
+ return attr.value
118
+ end
119
+ end
120
+ return ""
121
+ end
122
+
123
+
124
+
125
+
126
+
127
+ # 1. 要素が ns uri を持ってるかどうか確認
128
+ # 1-1. ns uri を持つ : prefix/uri ペア (prefix が nil もあり) の宣言がスコープ内にあるかどうか調べる
129
+ # 1-1-1. スコープ内にない : 要素の prefix の ns 宣言をする (nil の場合はデフォルト ns 宣言) 既に同じ prefix の宣言があるなら上書きする
130
+ # 1-2. ns uri を持たない : 要素が localName を持つかどうか確認
131
+ # 1-2-1 localName を持たない : 不明
132
+ # 1-2-2 localName を持つ : デフォルト ns 宣言が nil じゃないなら, この要素に nil のデフォルト ns 宣言を付ける
133
+ # prefix があって ns uri が nil というのは許されない!!!!
134
+ # 2. ns 宣言以外の属性を 1 個取り出し attr とする
135
+ # 3. attr が nil でないなら 4 へ
136
+ # 4. attr が ns を持っているか
137
+ # 4-1. ns あり : prefix がないか, prefix が宣言されてないか, prefix が既に別の ns に結び付けられている
138
+ # 4-1-1. prefix がダメ : ns に結び付けられている prefix が既にあるかどうか
139
+ # 4-1-1-1. ある : prefix をそれに変える
140
+ # 4-1-1-2. ない : prefix が nil でなく, まだスコープ内で宣言されていないか
141
+ # 4-1-1-2-1. 宣言されてない : 宣言する
142
+ # 4-1-1-2-2. prefix が nil または宣言されている : NS+index という prefix (まだ宣言されていないもの) に変え, 宣言する
143
+ # 4-2. ns なし : localName を持っているかどうか
144
+ # 4-2-1. localName なし : 不明
145
+ # 4-2-2. localName あり : 何もしない
146
+
147
+ #void Element.normalizeNamespaces()
148
+ def normalize_namespaces()
149
+ # non-namespace Attrs of Element
150
+ non_ns_attrs = Array.new()
151
+ # Pick up local namespace declarations
152
+ # for ( all DOM Level 2 valid local namespace declaration attributes of Element ) {
153
+ # if (the namespace declaration is invalid) {
154
+ # Note: The prefix xmlns is used only to declare namespace bindings and
155
+ # is by definition bound to the namespace name http://www.w3.org/2000/xmlns/.
156
+ # It must not be declared. No other prefix may be bound to this namespace name.
157
+ # ==> Report an error.
158
+ # } else {
159
+ # ==> Record the namespace declaration
160
+ # }
161
+ # }
162
+ #ns = Hash.new()
163
+ @attr_nodes.each do |n|
164
+ if n.name == "xmlns" then
165
+ # ns[nil] = n[0].data
166
+ elsif n.prefix == "xmlns" then
167
+ # ns[n.local_name.intern] = n[0].data
168
+ else
169
+ non_ns_attrs << n
170
+ end
171
+ end
172
+
173
+ # Fixup element's namespace
174
+ if self.namespace_uri then
175
+ # when Element's namespaceURI is not nil
176
+ # prefix / ns ペアが既にスコープ内に存在するかどうかの確認
177
+ # この flag チェックは変更しないとダメかも...
178
+ flag = false
179
+ if self.prefix.nil? then
180
+ #///////////////////////////////////
181
+ # is_default_namespace だとダメー
182
+ #///////////////////////////////////
183
+ #if self.is_default_namespace( self.namespace_uri ) then
184
+ # flag = true
185
+ #end
186
+ n = self
187
+ loop do
188
+ if n.nil? then
189
+ break
190
+ elsif n.node_type == ELEMENT_NODE then
191
+ if n.get_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns" ) == self.namespace_uri then
192
+ flag = true
193
+ break
194
+ end
195
+ end
196
+ n = n.parent_node
197
+ end
198
+ else
199
+ #///////////////////////////////////
200
+ # lookup_namespace_uri だとダメー
201
+ #///////////////////////////////////
202
+ #if self.lookup_namespace_uri( self.prefix ) == self.namespace_uri then
203
+ # flag = true
204
+ #end
205
+ if self.prefix == "xml" then
206
+ # ok?
207
+ flag = true
208
+ else
209
+ n = self
210
+ loop do
211
+ if n.nil? then
212
+ break
213
+ elsif n.node_type == ELEMENT_NODE then
214
+ if n.get_attribute_ns( "http://www.w3.org/2000/xmlns/", self.prefix ) == self.namespace_uri then
215
+ flag = true
216
+ break
217
+ end
218
+ end
219
+ n = n.parent_node
220
+ end
221
+ end
222
+ end
223
+ if flag then
224
+ # when Element's prefix/namespace pair (or default namespace, if no prefix) are within the scope of a binding
225
+ # ==> do nothing, declaration in scope is inherited
226
+ # See section "B.1.1: Scope of a binding" for an example
227
+ else
228
+ # ==> Create a local namespace declaration attr for this namespace,
229
+ # with Element's current prefix (or a default namespace, if
230
+ # no prefix). If there's a conflicting local declaration
231
+ # already present, change its value to use this namespace.
232
+ # See section "B.1.2: Conflicting namespace declaration" for an example
233
+ # // NOTE that this may break other nodes within this Element's
234
+ # // subtree, if they're already using this prefix.
235
+ # // They will be repaired when we reach them.
236
+ if self.prefix.nil? then
237
+ self.set_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns", self.namespace_uri )
238
+ else
239
+ self.set_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns:#{self.prefix}", self.namespace_uri )
240
+ end
241
+ end
242
+ else
243
+ # when Element has no namespace URI:
244
+ if self.local_name.nil? then
245
+ # when Element's localName is null
246
+ # // DOM Level 1 node
247
+ # ==> if in process of validation against a namespace aware schema
248
+ # (i.e XML Schema) report a fatal error: the processor can not recover
249
+ # in this situation.
250
+ # Otherwise, report an error: no namespace fixup will be performed on this node.
251
+ else
252
+ # when Element has no pseudo-prefix
253
+ if self.prefix.nil? and not self.is_default_namespace( nil ) then
254
+ # when there's a conflicting local default namespace declaration already present
255
+ # ==> change its value to use this empty namespace.
256
+ self.set_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns", "" )
257
+ elsif self.prefix and self.lookup_prefix( nil ) == self.prefix then
258
+ self.set_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns:#{self.prefix}", "" )
259
+ end
260
+ # // NOTE that this may break other nodes within this Element's
261
+ # // subtree, if they're already using the default namespaces.
262
+ # // They will be repaired when we reach them.
263
+ end
264
+ end
265
+
266
+ # Examine and polish the attributes
267
+ #for ( all non-namespace Attrs of Element )
268
+ non_ns_attrs.each do |attr|
269
+ if attr.namespace_uri then
270
+ if attr.prefix == "xml" then
271
+ # do nothing
272
+ # when attr has a namespace URI
273
+ elsif attr.prefix.nil? or self.lookup_namespace_uri( attr.prefix ) != attr.namespace_uri then
274
+ # when attribute has no prefix (default namespace decl does not apply to attributes)
275
+ # OR attribute prefix is not declared OR conflict: attribute has a prefix that conflicts with a binding
276
+ # already active in scope)
277
+ if not (new_prefix = self.lookup_prefix( attr.namespace_uri )).nil? then
278
+ # when (namespaceURI matches an in scope declaration of one or more prefixes)
279
+ # pick the most local binding available;
280
+ # if there is more than one pick one arbitrarily
281
+ # ==> change attribute's prefix.
282
+ attr.prefix = new_prefix
283
+ else
284
+ if not attr.prefix.nil? and self.lookup_namespace_uri( attr.prefix ).nil? then
285
+ # when the current prefix is not null and it has no in scope declaration
286
+ # ==> declare this prefix
287
+ self.set_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns:#{attr.prefix}", attr.namespace_uri )
288
+ else
289
+ # find a prefix following the pattern "NS" +index (starting at 1)
290
+ # make sure this prefix is not declared in the current scope.
291
+ # create a local namespace declaration attribute
292
+ #==> change attribute's prefix.
293
+ i = 0
294
+ loop do
295
+ i += 1
296
+ if self.lookup_namespace_uri( "NS#{i}" ).nil? then
297
+ self.set_attribute_ns( "http://www.w3.org/2000/xmlns/", "xmlns:NS#{i}", attr.namespace_uri )
298
+ break
299
+ end
300
+ end
301
+ attr.prefix = "NS#{i}"
302
+ end
303
+ end
304
+ end
305
+ else
306
+ # attr has no namespace URI
307
+ if attr.local_name.nil? then
308
+ # when attr has no localName
309
+ # = DOM Level 1 node
310
+ #==> if in process of validation against a namespace aware schema
311
+ # (i.e XML Schema) report a fatal error: the processor can not recover
312
+ # in this situation.
313
+ # Otherwise, report an error: no namespace fixup will be performed on this node.
314
+ else
315
+ # attr has no namespace URI and no prefix
316
+ # no action is required, since attrs don't use default
317
+ # ==> do nothing
318
+ end
319
+ end
320
+ end # end for-all-Attrs
321
+
322
+ # do this recursively
323
+ #for ( all child elements of Element )
324
+ self.each_child_node do |c|
325
+ if c.node_type == ELEMENT_NODE then
326
+ c.normalize_namespaces()
327
+ end
328
+ end # end Element.normalizeNamespaces
329
+ end
330
+
331
+ end
332
+ end