xml-smart 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. data/AUTHORS +4 -0
  2. data/COPYING +504 -0
  3. data/README.rdoc +55 -0
  4. data/Rakefile +15 -0
  5. data/example/EXAMPLE.xml +18 -0
  6. data/example/xpath_visual.rb +54 -0
  7. data/lib/xml/XSDtoRNG.xsl +448 -0
  8. data/lib/xml/smart.rb +177 -0
  9. data/lib/xml/smart_dom.rb +118 -0
  10. data/lib/xml/smart_domattribute.rb +34 -0
  11. data/lib/xml/smart_domattributeset.rb +62 -0
  12. data/lib/xml/smart_domelement.rb +213 -0
  13. data/lib/xml/smart_domnamespace.rb +32 -0
  14. data/lib/xml/smart_domnamespaceset.rb +125 -0
  15. data/lib/xml/smart_domnodeset.rb +59 -0
  16. data/lib/xml/smart_domother.rb +16 -0
  17. data/lib/xml/smart_domtext.rb +25 -0
  18. data/lib/xml/smart_qname.rb +34 -0
  19. data/test/1.xml +1 -0
  20. data/test/2.xml +1 -0
  21. data/test/3.xml +1 -0
  22. data/test/EXAMPLE-NS.xml +18 -0
  23. data/test/EXAMPLE-NSE.xml +18 -0
  24. data/test/EXAMPLE.str.xml +6 -0
  25. data/test/EXAMPLE.str.xml.test +6 -0
  26. data/test/EXAMPLE.tmp.xml +4 -0
  27. data/test/EXAMPLE.tmp.xml.test +4 -0
  28. data/test/EXAMPLE.xml +17 -0
  29. data/test/HELLO-MORE.xml +1 -0
  30. data/test/HELLO.rng +9 -0
  31. data/test/HELLO.xml +8 -0
  32. data/test/HELLO.xsd +16 -0
  33. data/test/XSL_BASE.xml +17 -0
  34. data/test/XSL_BASE.xml.test +16 -0
  35. data/test/XSL_DOCUMENT.xml +48 -0
  36. data/test/concurrent.xml +1 -0
  37. data/test/smartrunner.rb +25 -0
  38. data/test/tc_add.rb +21 -0
  39. data/test/tc_basic.rb +108 -0
  40. data/test/tc_concurrent.rb +73 -0
  41. data/test/tc_copy.rb +41 -0
  42. data/test/tc_create.rb +32 -0
  43. data/test/tc_delete.rb +52 -0
  44. data/test/tc_move_elements.rb +24 -0
  45. data/test/tc_namespace_default.rb +70 -0
  46. data/test/tc_namespace_detailed.rb +44 -0
  47. data/test/tc_namespace_find.rb +22 -0
  48. data/test/tc_nested.rb +26 -0
  49. data/test/tc_qname.rb +30 -0
  50. data/test/tc_relaxng.rb +30 -0
  51. data/test/tc_set_or_replace.rb +57 -0
  52. data/test/tc_sort.rb +18 -0
  53. data/test/tc_string.rb +41 -0
  54. data/test/tc_todoc.rb +27 -0
  55. data/test/tc_write.rb +19 -0
  56. data/test/tc_xinclude.rb +26 -0
  57. data/test/tc_xmlschema.rb +30 -0
  58. data/test/tc_xpath.rb +16 -0
  59. data/test/tc_xpath_attrs.rb +24 -0
  60. data/test/tc_xpath_functions.rb +12 -0
  61. data/test/tc_xpath_root.rb +23 -0
  62. data/test/tc_xsl.rb +22 -0
  63. data/xml-smart.gemspec +26 -0
  64. metadata +201 -0
@@ -0,0 +1,118 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+ def initialize(dom)
5
+ @dom = dom
6
+ @save_unformated = false
7
+ end
8
+
9
+ def ===(cls); self.is_a? cls; end
10
+
11
+ def root
12
+ Element.new(@dom.root)
13
+ end
14
+ def root=(nr)
15
+ @dom.root.replace(nr.instance_variable_get(:@element)) if nr.instance_of? Element
16
+ end
17
+
18
+ def find(path)
19
+ Element.new(@dom.root).find(path)
20
+ end
21
+
22
+ def to_s
23
+ @dom.to_s
24
+ end
25
+
26
+ def namespaces
27
+ @dom.custom_namespace_prefixes.merge @dom.user_custom_namespace_prefixes
28
+ end
29
+ def register_namespace(a,b)
30
+ if a.respond_to?(:to_s) && b.respond_to?(:to_s) && !@dom.custom_namespace_prefixes.key?(a.to_s) && @dom.custom_namespace_prefixes.value?(b.to_s)
31
+ @dom.user_custom_namespace_prefixes[a.to_s] = b.to_s
32
+ @dom.ns_update
33
+ true
34
+ else
35
+ false
36
+ end
37
+ end
38
+ def unregister_namespace(a)
39
+ if a.respond_to?(:to_s) && @dom.user_custom_namespace_prefixes.key?(a.to_s)
40
+ @dom.user_custom_namespace_prefixes.delete(a.to_s)
41
+ @dom.ns_update
42
+ true
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ def save_as(name)
49
+ raise Error, 'first parameter has to be a filename or filehandle' unless name.is_a?(String) || name.is_a?(IO)
50
+ begin
51
+ io = name.is_a?(String) ? ::Kernel::open(name,'w') : name
52
+ rescue
53
+ raise Error, "could not open #{name}"
54
+ end
55
+ ftext = if @save_unformated
56
+ @dom.root.serialize(:encoding => 'UTF-8', :save_with => Nokogiri::XML::Node::SaveOptions::NO_DECLARATION | Nokogiri::XML::Node::SaveOptions::AS_XML)
57
+ else
58
+ @dom.root.serialize(:encoding => 'UTF-8', :save_with => Nokogiri::XML::Node::SaveOptions::FORMAT | Nokogiri::XML::Node::SaveOptions::AS_XML)
59
+ end
60
+ io.write ftext
61
+ io.close
62
+ end
63
+
64
+ def save_unformated=(val); @save_unformated = (val.is_a?(TrueClass) ? true : false); end
65
+ def save_unformated?; @save_unformated; end
66
+
67
+ def xinclude!
68
+ Element.new(@dom.root).xinclude!
69
+ end
70
+
71
+ def self::smart_helper(node)
72
+ if node.instance_of? Nokogiri::XML::Element
73
+ Element.new(node)
74
+ elsif node.instance_of? Nokogiri::XML::Attr
75
+ Attribute.new(node)
76
+ elsif node.instance_of? Nokogiri::XML::NodeSet
77
+ NodeSet.new(node)
78
+ elsif node.instance_of?(String) || node.instance_of?(TrueClass) || node.instance_of?(FalseClass) || node.instance_of?(Float)
79
+ node
80
+ elsif node.instance_of? Nokogiri::XML::Text
81
+ Text.new(node)
82
+ elsif node.instance_of? Nokogiri::XML::Namespace
83
+ Namespace.new(node)
84
+ elsif node.instance_of? Nokogiri::XML::Document
85
+ Dom.new(node)
86
+ elsif node.nil?
87
+ nil
88
+ else
89
+ Other.new(node)
90
+ end
91
+ end
92
+
93
+ def validate_against(doc,&errbl)
94
+ raise Error, 'first parameter has to XML::Smart::Dom document' unless doc.instance_of? Dom
95
+ res = if doc.root.namespaces.has_ns?("http://relaxng.org/ns/structure/1.0")
96
+ Nokogiri::XML::RelaxNG.from_document(doc.instance_variable_get(:@dom)).validate(@dom)
97
+ elsif doc.root.namespaces.has_ns?("http://www.w3.org/2001/XMLSchema")
98
+ tdoc = Nokogiri::XSLT.parse(File.read(File.expand_path(File.dirname(__FILE__) + '/XSDtoRNG.xsl')))
99
+ rdoc = tdoc.transform(doc.instance_variable_get(:@dom))
100
+ Nokogiri::XML::RelaxNG.from_document(rdoc).validate(@dom)
101
+ end
102
+ res.each { |err| errbl.call err } if block_given?
103
+ res.empty?
104
+ end
105
+
106
+ def transform_with(doc,params=nil)
107
+ raise Error, 'first parameter has to XML::Smart::Dom document' unless doc.instance_of? Dom
108
+ res = Nokogiri::XSLT::Stylesheet.parse_stylesheet_doc(doc.instance_variable_get(:@dom)).transform(@dom,params)
109
+ if res.children.length != 0 && res.children.first.class == Nokogiri::XML::Text
110
+ Text.new(res.children.first).text
111
+ else
112
+ Dom::smart_helper(res)
113
+ end
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,34 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class Attribute
6
+ def initialize(attr)
7
+ @attr = attr
8
+ end
9
+
10
+ def ===(cls); self.is_a? cls; end
11
+
12
+ def to_s; @attr.content; end
13
+ def to_i; @attr.content.to_i; end
14
+ def to_f; @attr.content.to_f; end
15
+
16
+ def qname; QName.new @attr; end
17
+ def path; @attr.path; end
18
+
19
+ def value; @attr.content; end;
20
+ def value=(val); @attr.content = val; end;
21
+
22
+ def ==(other)
23
+ return false unless other
24
+ return false unless other.respond_to?(:unique_id)
25
+ unique_id == other.unique_id
26
+ end
27
+ def unique_id; @attr.pointer_id; end
28
+
29
+ def parent; Dom::smart_helper(@attr.parent); end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,62 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class AttributeSet
6
+ include Enumerable
7
+
8
+ def initialize(element)
9
+ @element = element
10
+ @set = @element.attributes
11
+ end
12
+
13
+ def ===(cls); self.is_a? cls; end
14
+
15
+ def has_attr?(a); @set.has_key?(a) end
16
+ alias :include? :has_attr?
17
+ alias :attr? :has_attr?
18
+ alias :member? :has_attr?
19
+
20
+ def [](name,attr=false)
21
+ return nil unless @set[name]
22
+ if attr == false
23
+ @element[name]
24
+ else
25
+ Attribute.new(@set[name])
26
+ end
27
+ end
28
+ def []=(name,value);
29
+ @element[name] = value
30
+ end
31
+
32
+ def length; @set.length; end
33
+ def empty?; @set.empty?; end
34
+ def delete_all!; @set.each { |k,a| a.remove }; end
35
+
36
+ def each(&block)
37
+ @set.each do |k,node|
38
+ block.call Dom::smart_helper(node)
39
+ end
40
+ end
41
+
42
+ def delete_at!(name)
43
+ tmp = @set[name]
44
+ if tmp === Nokogiri::XML::Attr
45
+ tmp.remove
46
+ true
47
+ else
48
+ false
49
+ end
50
+ end
51
+
52
+ def delete_if!(&block)
53
+ @set.each do |k,node|
54
+ node.remove if block.call(Dom::smart_helper(node))
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,213 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class Element
6
+ def initialize(element)
7
+ @element = element
8
+ end
9
+
10
+ def ===(cls); self.is_a? cls; end
11
+
12
+ def find(xpath)
13
+ Dom::smart_helper(@element.xpath_fast(xpath))
14
+ end
15
+
16
+ def add_helper(attrs)
17
+ if attrs.length>0 && attrs[0].is_a?(String)
18
+ pfx = ''
19
+ ns = nil
20
+ if attrs[0].sub!(/([^:]+):/, '')
21
+ pfx = $1
22
+ if @element.document.user_custom_namespace_prefixes.has_key?(pfx)
23
+ @element.document.custom_namespace_prefixes.each do |k,v|
24
+ if @element.document.user_custom_namespace_prefixes[pfx] == v
25
+ ns = @element.document.user_custom_namespace_prefixes[pfx]
26
+ end
27
+ end
28
+ end
29
+ if ns.nil?
30
+ if @element.document.custom_namespace_prefixes.has_key?(pfx)
31
+ ns = @element.document.custom_namespace_prefixes[pfx]
32
+ else
33
+ raise Error, 'No valid namespace'
34
+ end
35
+ end
36
+ end
37
+ tmp = Nokogiri::XML::Node.new attrs[0], @element.document
38
+ unless ns.nil?
39
+ @element.namespace_scopes.each do |nss|
40
+ tmp.namespace = nss if nss.href == ns
41
+ end
42
+ end
43
+ [1,2].each do |i|
44
+ if attrs.length > i
45
+ case attrs[i]
46
+ when Hash
47
+ attrs[i].each do |k,v|
48
+ if k.respond_to?(:to_s)
49
+ tmp[k.to_s] = v.respond_to?(:to_s) ? v.to_s : ''
50
+ else
51
+ raise Error, 'use something that has provides #to_s'
52
+ end
53
+ end
54
+ else
55
+ tmp.content = attrs[i].respond_to?(:to_s) ? attrs[i].to_s : ''
56
+ end
57
+ end
58
+ end
59
+ return [tmp,false]
60
+ end
61
+ if attrs.length == 1 && attrs[0].is_a?(XML::Smart::Dom::Element)
62
+ ele = attrs[0].instance_variable_get(:@element)
63
+ same = ele.document.root.pointer_id == @element.document.root.pointer_id
64
+ return [same ? ele : ele.dup, !same]
65
+ end
66
+ if attrs.length == 1 && attrs[0].is_a?(XML::Smart::Dom::NodeSet)
67
+ nos = attrs[0].instance_variable_get(:@nodeset)
68
+ if nos.length > 0
69
+ same = nos.first.document.root.pointer_id == @element.document.root.pointer_id
70
+ if same
71
+ return [nos, false]
72
+ else
73
+ tnos = nos.map{|e|e.dup}
74
+ return [Nokogiri::XML::NodeSet.new(nos.first.document,tnos), true]
75
+ end
76
+ else
77
+ return [nos, false]
78
+ end
79
+ end
80
+ if attrs.length == 2 && attrs[0].is_a?(XML::Smart::Dom::Element) && (attrs[1] == XML::Smart::COPY || attrs[1] == XML::Smart::MOVE)
81
+ ele = attrs[0].instance_variable_get(:@element)
82
+ same = ele.document.root.pointer_id == @element.document.root.pointer_id
83
+ return [attrs[1] == XML::Smart::COPY ? ele.dup : ele, !same]
84
+ end
85
+ if attrs.length == 2 && attrs[0].is_a?(XML::Smart::Dom::NodeSet) && (attrs[1] == XML::Smart::COPY || attrs[1] == XML::Smart::MOVE)
86
+ nos = attrs[0].instance_variable_get(:@nodeset)
87
+ if nos.length > 0
88
+ same = nos.first.document.root.pointer_id == @element.document.root.pointer_id
89
+ if attrs[1] == XML::Smart::COPY
90
+ tnos = nos.map{|e|e.dup}
91
+ nos = Nokogiri::XML::NodeSet.new(nos.first.document,tnos)
92
+ end
93
+ return [Nokogiri::XML::NodeSet.new(nos.first.document,tnos), true]
94
+ return [nos, !same]
95
+ else
96
+ return [nos, false]
97
+ end
98
+ end
99
+ return [nil, false]
100
+ end
101
+ private :add_helper
102
+ def add(*attrs)
103
+ tmp, update = add_helper(attrs)
104
+ res = Dom::smart_helper(@element.add_child tmp)
105
+ if update
106
+ @element.document.custom_namespace_prefixes_update
107
+ @element.document.ns_update
108
+ end
109
+ res
110
+ end
111
+ def add_before(*attrs)
112
+ tmp, update = add_helper(attrs)
113
+ res = Dom::smart_helper(@element.add_previous_sibling tmp)
114
+ if update
115
+ @element.document.custom_namespace_prefixes_update
116
+ @element.document.ns_update
117
+ end
118
+ res
119
+ end
120
+ def add_after(*attrs)
121
+ tmp, update = add_helper(attrs)
122
+ res = Dom::smart_helper(@element.add_next_sibling tmp)
123
+ if update
124
+ @element.document.custom_namespace_prefixes_update
125
+ @element.document.ns_update
126
+ end
127
+ res
128
+ end
129
+
130
+ def dump; @element.to_s; end
131
+ def to_s; @element.content; end
132
+ def to_i; @element.content.to_i; end
133
+ def to_f; @element.content.to_f; end
134
+
135
+ def namespace?; !@element.namespace.nil?; end
136
+ def namespace; namespace? ? Namespace.new(@element.namespace) : nil; end
137
+ def namespace=(n)
138
+ n = case n
139
+ when Namespace
140
+ n.prefix
141
+ when String
142
+ n
143
+ else
144
+ return
145
+ end
146
+ tmp = @element.document.custom_namespace_prefixes[n] || @element.document.user_custom_namespace_prefixes[n]
147
+ unless tmp.nil?
148
+ @element.namespace_scopes.each do |nss|
149
+ @element.namespace = nss if nss.href == tmp
150
+ end
151
+ end
152
+ end
153
+ def namespaces; NamespaceSet.new(self,@element); end
154
+
155
+ def xinclude!
156
+ @element.do_xinclude
157
+ @element.document.custom_namespace_prefixes_update
158
+ @element.document.ns_update
159
+ true
160
+ end
161
+
162
+ def replace_by(n)
163
+ case n
164
+ when Element; Element.new @element.replace(n.instance_variable_get(:@element))
165
+ when NodeSet; NodeSet.new @element.replace(n.instance_variable_get(:@nodeset))
166
+ else
167
+ nil
168
+ end
169
+ end
170
+
171
+ def qname; QName.new @element; end
172
+ def attributes; AttributeSet.new @element; end
173
+
174
+ def text; @element.xpath_fast("string(text())"); end
175
+ def text=(t); @element.content = t.to_s if t.respond_to? :to_s; end
176
+
177
+ def children; find('*'); end
178
+ def children?; find('*').length > 0 end
179
+ def parent
180
+ Dom::smart_helper(@element.parent)
181
+ end
182
+ def parent?; !@element.parent.nil?; end
183
+
184
+ def empty?; @element.blank?; end
185
+ def mixed?;
186
+ @element.xpath_fast('*').length > 0 && @element.xpath_fast("string(text())") != '';
187
+ end
188
+ def text_only?;
189
+ @element.xpath_fast('*').length == 0 && @element.xpath_fast("string(text())") != '';
190
+ end
191
+ def element_only?;
192
+ @element.xpath_fast('*').length > 0 && @element.xpath_fast("string(text())") == '';
193
+ end
194
+
195
+ def path; @element.path; end
196
+
197
+ def ==(other)
198
+ return false unless other
199
+ return false unless other.respond_to?(:unique_id)
200
+ unique_id == other.unique_id
201
+ end
202
+ def unique_id; @element.pointer_id; end
203
+
204
+ def to_doc
205
+ doc = Nokogiri::XML::Document.new
206
+ doc.root = @element
207
+ dom = Dom.new(doc)
208
+ end
209
+ end
210
+
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,32 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class Namespace
6
+ def initialize(ns)
7
+ @ns = ns
8
+ end
9
+
10
+ def ===(cls); self.is_a? cls; end
11
+
12
+ def href; @ns.href; end
13
+ alias :to_s :href
14
+
15
+ def prefix
16
+ if @ns.prefix
17
+ @ns.prefix
18
+ else
19
+ @ns.document.custom_namespace_prefixes.find{|k,v| v == @ns.href}[0]
20
+ end
21
+ end
22
+
23
+ def ==(other)
24
+ return false unless other
25
+ return false unless other.respond_to?(:to_s)
26
+ to_s == other.to_s
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,125 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class NamespaceSet
6
+ include Enumerable
7
+
8
+ def initialize(parent,node)
9
+ @parent = parent
10
+ @node = node
11
+ end
12
+
13
+ def ===(cls); self.is_a? cls; end
14
+
15
+ def has_ns?(a); @node.namespace_definitions.one?{|e| e.href == a || e.prefix == a}; end
16
+ alias :include? :has_ns?
17
+ alias :ns? :has_ns?
18
+ alias :member? :has_ns?
19
+
20
+ def [](name)
21
+ if name.nil? || name.respond_to?(:to_s)
22
+ name = name.to_s unless name.nil?
23
+ name = nil if name =~ /^xmlns\d*$/
24
+ nd = @node.namespace_definitions.find{|n| n.prefix == name}
25
+ (name.respond_to?(:to_s) || name.nil?) && nd ? Namespace.new(nd) : nil;
26
+ end
27
+ end
28
+ def []=(name,value)
29
+ self.add(name,value)
30
+ end
31
+
32
+ def add(name,value)
33
+ if (name.respond_to?(:to_s) || name.nil?) && value.respond_to?(:to_s)
34
+ nnod = Nokogiri::XML::Node.new(@node.name,@node.document)
35
+ nnew = Element.new(nnod)
36
+ nold = Element.new(@node)
37
+ nold.attributes.each do |attr|
38
+ nnew.attributes[attr.qname.name] = attr.value
39
+ end
40
+ ns = nnod.add_namespace_definition(name,value)
41
+ @node.namespace_definitions.each do |ns|
42
+ nnod.add_namespace_definition(ns.prefix,ns.href)
43
+ end
44
+ nnew.add(nold.children)
45
+ nold.replace_by(nnew)
46
+ @node = nnod
47
+ @parent.instance_variable_set(:@element,@node)
48
+ @node.document.custom_namespace_prefixes_update
49
+ @node.document.ns_update
50
+ Namespace.new(ns)
51
+ end
52
+ end
53
+
54
+ def length; @node.namespace_definitions.length; end
55
+ def empty?; @node.namespace_definitions.empty?; end
56
+ def delete_all!
57
+ nnod = Nokogiri::XML::Node.new(@node.name,@node.document)
58
+ nnew = Element.new(nnod)
59
+ nold = Element.new(@node)
60
+ nold.attributes.each do |attr|
61
+ nnew.attributes[attr.qname.name] = attr.value
62
+ end
63
+ nnew.add(nold.children)
64
+ nold.replace_by(nnew)
65
+ @node = nnod
66
+ @parent.instance_variable_set(:@element,@node)
67
+ @node.document.custom_namespace_prefixes_update
68
+ @node.document.ns_update
69
+ nil
70
+ end
71
+
72
+ def each(&block)
73
+ @node.namespace_definitions.each do |ns|
74
+ block.call Namespace.new(ns)
75
+ end
76
+ end
77
+
78
+ def delete_at(name)
79
+ if (name.respond_to?(:to_s) || name.nil?)
80
+ return false unless @node.namespace_definitions.one?{|e| e.prefix == name}
81
+
82
+ nnod = Nokogiri::XML::Node.new(@node.name,@node.document)
83
+ nnew = Element.new(nnod)
84
+ nold = Element.new(@node)
85
+ nold.attributes.each do |attr|
86
+ nnew.attributes[attr.qname.name] = attr.value
87
+ end
88
+ @node.namespace_definitions.each do |ns|
89
+ nnod.add_namespace_definition(ns.prefix,ns.href) unless ns.prefix == name
90
+ end
91
+ nnew.add(nold.children)
92
+ nold.replace_by(nnew)
93
+ @node = nnod
94
+ @parent.instance_variable_set(:@element,@node)
95
+ @node.document.custom_namespace_prefixes_update
96
+ @node.document.ns_update
97
+ true
98
+ else
99
+ false
100
+ end
101
+ end
102
+
103
+ def delete_if(&block)
104
+ nnod = Nokogiri::XML::Node.new(@node.name,@node.document)
105
+ nnew = Element.new(nnod)
106
+ nold = Element.new(@node)
107
+ nold.attributes.each do |attr|
108
+ nnew.attributes[attr.qname.name] = attr.value
109
+ end
110
+ @node.namespace_definitions.each do |ns|
111
+ nnod.add_namespace_definition(ns.prefix,ns.href) unless block.call(Dom::smart_helper(ns))
112
+ end
113
+ nnew.add(nold.children)
114
+ nold.replace_by(nnew)
115
+ @node = nnod
116
+ @parent.instance_variable_set(:@element,@node)
117
+ @node.document.custom_namespace_prefixes_update
118
+ @node.document.ns_update
119
+ self
120
+ end
121
+ end
122
+
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,59 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class NodeSet
6
+ include Enumerable
7
+
8
+ def initialize(nodeset)
9
+ @nodeset = nodeset
10
+ end
11
+
12
+ def ===(cls); self.is_a? cls; end
13
+
14
+ def first; Dom::smart_helper(@nodeset.first); end
15
+ def last; Dom::smart_helper(@nodeset.last); end
16
+ def at(*a); Dom::smart_helper(@nodeset[*a]); end
17
+ def [](*a); Dom::smart_helper(@nodeset[*a]); end
18
+
19
+ def length; @nodeset.length; end
20
+ def empty?; @nodeset.empty?; end
21
+ def delete_all!; @nodeset.remove; @nodeset.to_a.each { |n| @nodeset.delete(n) }; true end
22
+
23
+ def each(&block)
24
+ @nodeset.each do |node|
25
+ block.call Dom::smart_helper(node)
26
+ end
27
+ end
28
+
29
+ def delete_at(*a)
30
+ tmp = @nodeset[*a]
31
+ case tmp
32
+ when Nokogiri::XML::NodeSet
33
+ tmp.each { |node| @nodeset.delete(node.remove) }
34
+ true
35
+ when Nokogiri::XML::Node
36
+ @nodeset.delete(tmp.remove)
37
+ true
38
+ else
39
+ false
40
+ end
41
+ end
42
+
43
+ def delete_if(&block)
44
+ tmp = []
45
+ @nodeset.each do |node|
46
+ if block.call(Dom::smart_helper(node))
47
+ tmp << node.remove
48
+ end
49
+ end
50
+ tmp.each { |t| @nodeset.delete(t) }
51
+ self
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,16 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class Other < Text
6
+ def otype
7
+ case @text
8
+ when Nokogiri::XML::Comment; :comment
9
+ else; :unknown
10
+ end
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module XML
2
+ module Smart
3
+ class Dom
4
+
5
+ class Text
6
+ def initialize(text); @text = text; end
7
+
8
+ def ===(cls); self.is_a? cls; end
9
+
10
+ def dump; to_s; end
11
+ def to_s; @text.content.to_s; end
12
+ def to_f; @text.content.to_f; end
13
+ def to_i; @text.content.to_i; end
14
+
15
+ def text; @text.content; end
16
+ def text=(t); @text.content = t.to_s if t.respond_to? :to_s; end
17
+
18
+ def parent; Node.new(@text.parent); end
19
+
20
+ def path; @text.path; end
21
+ end
22
+
23
+ end
24
+ end
25
+ end