nokogiri 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (200) hide show
  1. data/.autotest +14 -2
  2. data/CHANGELOG.ja.rdoc +38 -0
  3. data/CHANGELOG.rdoc +43 -0
  4. data/Manifest.txt +80 -5
  5. data/README.ja.rdoc +12 -11
  6. data/README.rdoc +4 -2
  7. data/Rakefile +103 -173
  8. data/bin/nokogiri +47 -0
  9. data/ext/nokogiri/extconf.rb +19 -13
  10. data/ext/nokogiri/html_document.c +39 -3
  11. data/ext/nokogiri/html_document.h +1 -1
  12. data/ext/nokogiri/html_element_description.c +272 -0
  13. data/ext/nokogiri/html_element_description.h +10 -0
  14. data/ext/nokogiri/html_entity_lookup.h +1 -1
  15. data/ext/nokogiri/html_sax_parser.h +1 -1
  16. data/ext/nokogiri/{native.c → nokogiri.c} +11 -3
  17. data/ext/nokogiri/{native.h → nokogiri.h} +18 -4
  18. data/ext/nokogiri/xml_attr.c +14 -5
  19. data/ext/nokogiri/xml_attr.h +1 -1
  20. data/ext/nokogiri/xml_cdata.c +15 -6
  21. data/ext/nokogiri/xml_cdata.h +1 -1
  22. data/ext/nokogiri/xml_comment.c +13 -4
  23. data/ext/nokogiri/xml_comment.h +1 -1
  24. data/ext/nokogiri/xml_document.c +50 -41
  25. data/ext/nokogiri/xml_document.h +1 -1
  26. data/ext/nokogiri/xml_document_fragment.c +12 -4
  27. data/ext/nokogiri/xml_document_fragment.h +1 -1
  28. data/ext/nokogiri/xml_dtd.c +1 -1
  29. data/ext/nokogiri/xml_dtd.h +1 -1
  30. data/ext/nokogiri/xml_entity_reference.c +13 -4
  31. data/ext/nokogiri/xml_entity_reference.h +1 -1
  32. data/ext/nokogiri/xml_io.h +1 -1
  33. data/ext/nokogiri/xml_namespace.c +69 -0
  34. data/ext/nokogiri/xml_namespace.h +12 -0
  35. data/ext/nokogiri/xml_node.c +232 -124
  36. data/ext/nokogiri/xml_node.h +3 -4
  37. data/ext/nokogiri/xml_node_set.c +206 -19
  38. data/ext/nokogiri/xml_node_set.h +1 -1
  39. data/ext/nokogiri/xml_processing_instruction.c +14 -4
  40. data/ext/nokogiri/xml_processing_instruction.h +1 -1
  41. data/ext/nokogiri/xml_reader.c +87 -7
  42. data/ext/nokogiri/xml_reader.h +1 -1
  43. data/ext/nokogiri/xml_relax_ng.c +106 -0
  44. data/ext/nokogiri/xml_relax_ng.h +9 -0
  45. data/ext/nokogiri/xml_sax_parser.c +122 -2
  46. data/ext/nokogiri/xml_sax_parser.h +1 -1
  47. data/ext/nokogiri/xml_sax_push_parser.c +1 -0
  48. data/ext/nokogiri/xml_sax_push_parser.h +1 -1
  49. data/ext/nokogiri/xml_schema.c +107 -0
  50. data/ext/nokogiri/xml_schema.h +9 -0
  51. data/ext/nokogiri/xml_syntax_error.h +1 -1
  52. data/ext/nokogiri/xml_text.c +10 -3
  53. data/ext/nokogiri/xml_text.h +1 -1
  54. data/ext/nokogiri/xml_xpath.h +1 -1
  55. data/ext/nokogiri/xml_xpath_context.h +1 -1
  56. data/ext/nokogiri/xslt_stylesheet.c +29 -16
  57. data/ext/nokogiri/xslt_stylesheet.h +1 -1
  58. data/lib/action-nokogiri.rb +7 -1
  59. data/lib/nokogiri.rb +21 -5
  60. data/lib/nokogiri/css/generated_parser.rb +49 -14
  61. data/lib/nokogiri/css/generated_tokenizer.rb +2 -2
  62. data/lib/nokogiri/css/node.rb +13 -3
  63. data/lib/nokogiri/css/parser.rb +8 -0
  64. data/lib/nokogiri/css/parser.y +7 -7
  65. data/lib/nokogiri/css/tokenizer.rb +2 -0
  66. data/lib/nokogiri/css/xpath_visitor.rb +10 -6
  67. data/lib/nokogiri/decorators/hpricot/node.rb +1 -1
  68. data/lib/nokogiri/decorators/hpricot/node_set.rb +2 -2
  69. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +2 -0
  70. data/lib/nokogiri/decorators/slop.rb +3 -1
  71. data/lib/nokogiri/ffi/html/document.rb +37 -0
  72. data/lib/nokogiri/ffi/html/element_description.rb +85 -0
  73. data/lib/nokogiri/ffi/html/entity_lookup.rb +16 -0
  74. data/lib/nokogiri/ffi/html/sax/parser.rb +21 -0
  75. data/lib/nokogiri/ffi/io_callbacks.rb +32 -0
  76. data/lib/nokogiri/ffi/libxml.rb +314 -0
  77. data/lib/nokogiri/ffi/structs/common_node.rb +26 -0
  78. data/lib/nokogiri/ffi/structs/html_elem_desc.rb +24 -0
  79. data/lib/nokogiri/ffi/structs/html_entity_desc.rb +13 -0
  80. data/lib/nokogiri/ffi/structs/xml_alloc.rb +16 -0
  81. data/lib/nokogiri/ffi/structs/xml_attr.rb +19 -0
  82. data/lib/nokogiri/ffi/structs/xml_buffer.rb +16 -0
  83. data/lib/nokogiri/ffi/structs/xml_document.rb +108 -0
  84. data/lib/nokogiri/ffi/structs/xml_dtd.rb +26 -0
  85. data/lib/nokogiri/ffi/structs/xml_node.rb +28 -0
  86. data/lib/nokogiri/ffi/structs/xml_node_set.rb +53 -0
  87. data/lib/nokogiri/ffi/structs/xml_notation.rb +11 -0
  88. data/lib/nokogiri/ffi/structs/xml_ns.rb +15 -0
  89. data/lib/nokogiri/ffi/structs/xml_relax_ng.rb +14 -0
  90. data/lib/nokogiri/ffi/structs/xml_sax_handler.rb +51 -0
  91. data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +14 -0
  92. data/lib/nokogiri/ffi/structs/xml_schema.rb +13 -0
  93. data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +31 -0
  94. data/lib/nokogiri/ffi/structs/xml_text_reader.rb +12 -0
  95. data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +37 -0
  96. data/lib/nokogiri/ffi/structs/xml_xpath_object.rb +35 -0
  97. data/lib/nokogiri/ffi/structs/xml_xpath_parser_context.rb +20 -0
  98. data/lib/nokogiri/ffi/structs/xslt_stylesheet.rb +13 -0
  99. data/lib/nokogiri/ffi/xml/attr.rb +41 -0
  100. data/lib/nokogiri/ffi/xml/cdata.rb +19 -0
  101. data/lib/nokogiri/ffi/xml/comment.rb +18 -0
  102. data/lib/nokogiri/ffi/xml/document.rb +107 -0
  103. data/lib/nokogiri/ffi/xml/document_fragment.rb +26 -0
  104. data/lib/nokogiri/ffi/xml/dtd.rb +42 -0
  105. data/lib/nokogiri/ffi/xml/entity_reference.rb +19 -0
  106. data/lib/nokogiri/ffi/xml/namespace.rb +38 -0
  107. data/lib/nokogiri/ffi/xml/node.rb +380 -0
  108. data/lib/nokogiri/ffi/xml/node_set.rb +130 -0
  109. data/lib/nokogiri/ffi/xml/processing_instruction.rb +20 -0
  110. data/lib/nokogiri/ffi/xml/reader.rb +217 -0
  111. data/lib/nokogiri/ffi/xml/relax_ng.rb +51 -0
  112. data/lib/nokogiri/ffi/xml/sax/parser.rb +148 -0
  113. data/lib/nokogiri/ffi/xml/sax/push_parser.rb +38 -0
  114. data/lib/nokogiri/ffi/xml/schema.rb +55 -0
  115. data/lib/nokogiri/ffi/xml/syntax_error.rb +76 -0
  116. data/lib/nokogiri/ffi/xml/text.rb +18 -0
  117. data/lib/nokogiri/ffi/xml/xpath.rb +19 -0
  118. data/lib/nokogiri/ffi/xml/xpath_context.rb +135 -0
  119. data/lib/nokogiri/ffi/xslt/stylesheet.rb +47 -0
  120. data/lib/nokogiri/hpricot.rb +14 -3
  121. data/lib/nokogiri/html.rb +11 -46
  122. data/lib/nokogiri/html/builder.rb +27 -1
  123. data/lib/nokogiri/html/document.rb +62 -6
  124. data/lib/nokogiri/html/document_fragment.rb +15 -0
  125. data/lib/nokogiri/html/element_description.rb +23 -0
  126. data/lib/nokogiri/html/entity_lookup.rb +2 -0
  127. data/lib/nokogiri/html/sax/parser.rb +27 -1
  128. data/lib/nokogiri/version.rb +26 -1
  129. data/lib/nokogiri/version_warning.rb +11 -0
  130. data/lib/nokogiri/xml.rb +25 -51
  131. data/lib/nokogiri/xml/builder.rb +166 -10
  132. data/lib/nokogiri/xml/cdata.rb +3 -1
  133. data/lib/nokogiri/xml/document.rb +39 -6
  134. data/lib/nokogiri/xml/document_fragment.rb +41 -1
  135. data/lib/nokogiri/xml/dtd.rb +3 -1
  136. data/lib/nokogiri/xml/entity_declaration.rb +3 -1
  137. data/lib/nokogiri/xml/fragment_handler.rb +24 -3
  138. data/lib/nokogiri/xml/namespace.rb +7 -0
  139. data/lib/nokogiri/xml/node.rb +314 -65
  140. data/lib/nokogiri/xml/node/save_options.rb +12 -2
  141. data/lib/nokogiri/xml/node_set.rb +58 -8
  142. data/lib/nokogiri/xml/parse_options.rb +80 -0
  143. data/lib/nokogiri/xml/processing_instruction.rb +2 -0
  144. data/lib/nokogiri/xml/reader.rb +42 -3
  145. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  146. data/lib/nokogiri/xml/sax.rb +0 -7
  147. data/lib/nokogiri/xml/sax/document.rb +84 -0
  148. data/lib/nokogiri/xml/sax/parser.rb +38 -2
  149. data/lib/nokogiri/xml/sax/push_parser.rb +12 -0
  150. data/lib/nokogiri/xml/schema.rb +65 -0
  151. data/lib/nokogiri/xml/syntax_error.rb +11 -0
  152. data/lib/nokogiri/xml/xpath.rb +1 -1
  153. data/lib/nokogiri/xml/xpath_context.rb +2 -0
  154. data/lib/nokogiri/xslt.rb +21 -1
  155. data/lib/nokogiri/xslt/stylesheet.rb +19 -0
  156. data/lib/xsd/xmlparser/nokogiri.rb +12 -2
  157. data/tasks/test.rb +42 -19
  158. data/test/css/test_parser.rb +29 -0
  159. data/test/ffi/test_document.rb +35 -0
  160. data/test/files/address_book.rlx +12 -0
  161. data/test/files/address_book.xml +10 -0
  162. data/test/files/po.xml +32 -0
  163. data/test/files/po.xsd +66 -0
  164. data/test/helper.rb +38 -8
  165. data/test/html/sax/test_parser.rb +12 -0
  166. data/test/html/test_builder.rb +25 -2
  167. data/test/html/test_document.rb +91 -20
  168. data/test/html/test_document_fragment.rb +97 -0
  169. data/test/html/test_element_description.rb +95 -0
  170. data/test/html/test_node.rb +66 -3
  171. data/test/test_convert_xpath.rb +1 -1
  172. data/test/test_memory_leak.rb +57 -18
  173. data/test/test_nokogiri.rb +24 -2
  174. data/test/test_reader.rb +77 -0
  175. data/test/test_xslt_transforms.rb +120 -82
  176. data/test/xml/node/test_subclass.rb +44 -0
  177. data/test/xml/sax/test_parser.rb +9 -0
  178. data/test/xml/sax/test_push_parser.rb +24 -0
  179. data/test/xml/test_attr.rb +7 -0
  180. data/test/xml/test_builder.rb +48 -0
  181. data/test/xml/test_cdata.rb +19 -0
  182. data/test/xml/test_comment.rb +6 -0
  183. data/test/xml/test_document.rb +101 -2
  184. data/test/xml/test_document_fragment.rb +55 -3
  185. data/test/xml/test_entity_reference.rb +4 -0
  186. data/test/xml/test_namespace.rb +43 -0
  187. data/test/xml/test_node.rb +255 -8
  188. data/test/xml/test_node_attributes.rb +34 -0
  189. data/test/xml/test_node_encoding.rb +9 -2
  190. data/test/xml/test_node_set.rb +197 -1
  191. data/test/xml/test_parse_options.rb +52 -0
  192. data/test/xml/test_processing_instruction.rb +5 -0
  193. data/test/xml/test_relax_ng.rb +60 -0
  194. data/test/xml/test_schema.rb +65 -0
  195. data/test/xml/test_text.rb +5 -0
  196. data/test/xml/test_unparented_node.rb +3 -3
  197. metadata +128 -12
  198. data/lib/nokogiri/xml/comment.rb +0 -6
  199. data/lib/nokogiri/xml/element.rb +0 -6
  200. data/lib/nokogiri/xml/text.rb +0 -6
@@ -0,0 +1,38 @@
1
+ module Nokogiri
2
+ module XML
3
+ class Namespace # :nodoc:
4
+
5
+ attr_accessor :cstruct # :nodoc:
6
+ attr_accessor :document # :nodoc:
7
+
8
+ def prefix # :nodoc:
9
+ cstruct[:prefix].nil? ? nil : cstruct[:prefix] # TODO: encoding?
10
+ end
11
+
12
+ def href # :nodoc:
13
+ cstruct[:href].nil? ? nil : cstruct[:href] # TODO: encoding?
14
+ end
15
+
16
+ class << self
17
+ def wrap(document, node_struct) # :nodoc:
18
+ if node_struct.is_a?(FFI::Pointer)
19
+ # cast native pointers up into a node cstruct
20
+ return nil if node_struct.null?
21
+ node_struct = LibXML::XmlNs.new(node_struct)
22
+ end
23
+
24
+ ruby_node = node_struct.ruby_node
25
+ return ruby_node unless ruby_node.nil?
26
+
27
+ ns = Nokogiri::XML::Namespace.allocate
28
+ ns.document = document.ruby_doc
29
+ ns.cstruct = node_struct
30
+
31
+ ns.cstruct.ruby_node = ns
32
+ ns
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,380 @@
1
+ module Nokogiri
2
+ module XML
3
+ class Node
4
+
5
+ attr_accessor :cstruct # :nodoc:
6
+
7
+ def pointer_id # :nodoc:
8
+ cstruct.pointer
9
+ end
10
+
11
+ def encode_special_chars(string) # :nodoc:
12
+ char_ptr = LibXML.xmlEncodeSpecialChars(self[:doc], string)
13
+ encoded = char_ptr.read_string
14
+ # TODO: encoding?
15
+ LibXML.xmlFree(char_ptr)
16
+ encoded
17
+ end
18
+
19
+ def internal_subset # :nodoc:
20
+ return nil if cstruct[:doc].null?
21
+ doc = cstruct.document
22
+ dtd = LibXML.xmlGetIntSubset(doc)
23
+ return nil if dtd.null?
24
+ Node.wrap(dtd)
25
+ end
26
+
27
+ def dup(deep = 1) # :nodoc:
28
+ dup_ptr = LibXML.xmlDocCopyNode(cstruct, cstruct.document, deep)
29
+ return nil if dup_ptr.null?
30
+ Node.wrap(dup_ptr, self.class)
31
+ end
32
+
33
+ def unlink # :nodoc:
34
+ LibXML.xmlUnlinkNode(cstruct)
35
+ cstruct.keep_reference_from_document!
36
+ self
37
+ end
38
+
39
+ def blank? # :nodoc:
40
+ LibXML.xmlIsBlankNode(cstruct) == 1
41
+ end
42
+
43
+ def next_sibling # :nodoc:
44
+ cstruct_node_from :next
45
+ end
46
+
47
+ def previous_sibling # :nodoc:
48
+ cstruct_node_from :prev
49
+ end
50
+
51
+ def replace_with_node(new_node) # :nodoc:
52
+ LibXML.xmlReplaceNode(cstruct, new_node.cstruct)
53
+ Node.send(:relink_namespace, new_node.cstruct)
54
+ self
55
+ end
56
+
57
+ def children # :nodoc:
58
+ return NodeSet.new(nil) if cstruct[:children].null?
59
+ child = Node.wrap(cstruct[:children])
60
+
61
+ set = NodeSet.new child.document
62
+ set_ptr = LibXML.xmlXPathNodeSetCreate(child.cstruct)
63
+
64
+ set.cstruct = LibXML::XmlNodeSet.new(set_ptr)
65
+ return set unless child
66
+
67
+ child_ptr = child.cstruct[:next]
68
+ while ! child_ptr.null?
69
+ child = Node.wrap(child_ptr)
70
+ LibXML.xmlXPathNodeSetAdd(set.cstruct, child.cstruct)
71
+ child_ptr = child.cstruct[:next]
72
+ end
73
+
74
+ return set
75
+ end
76
+
77
+ def child # :nodoc:
78
+ (val = cstruct[:children]).null? ? nil : Node.wrap(val)
79
+ end
80
+
81
+ def key?(attribute) # :nodoc:
82
+ ! (prop = LibXML.xmlHasProp(cstruct, attribute.to_s)).null?
83
+ end
84
+
85
+ def namespaced_key?(attribute, namespace) # :nodoc:
86
+ prop = LibXML.xmlHasNsProp(cstruct, attribute.to_s,
87
+ namespace.nil? ? nil : namespace.to_s)
88
+ prop.null? ? false : true
89
+ end
90
+
91
+ def []=(property, value) # :nodoc:
92
+ LibXML.xmlSetProp(cstruct, property, value)
93
+ value
94
+ end
95
+
96
+ def get(attribute) # :nodoc:
97
+ return nil unless attribute
98
+ propstr = LibXML.xmlGetProp(cstruct, attribute.to_s)
99
+ return nil if propstr.null?
100
+ rval = propstr.read_string # TODO: encoding?
101
+ LibXML.xmlFree(propstr)
102
+ rval
103
+ end
104
+
105
+ def set_namespace(namespace)
106
+ LibXML.xmlSetNs(cstruct, namespace.cstruct)
107
+ self
108
+ end
109
+
110
+ def attribute(name) # :nodoc:
111
+ raise "Node#attribute not implemented yet"
112
+ end
113
+
114
+ def attribute_with_ns(name, namespace) # :nodoc:
115
+ prop = LibXML.xmlHasNsProp(cstruct, name.to_s,
116
+ namespace.nil? ? NULL : namespace.to_s)
117
+ return prop if prop.null?
118
+ Node.wrap(prop)
119
+ end
120
+
121
+ def attribute_nodes # :nodoc:
122
+ attr = []
123
+ prop_cstruct = cstruct[:properties]
124
+ while ! prop_cstruct.null?
125
+ prop = Node.wrap(prop_cstruct)
126
+ attr << prop
127
+ prop_cstruct = prop.cstruct[:next]
128
+ end
129
+ attr
130
+ end
131
+
132
+ def namespace # :nodoc:
133
+ cstruct[:ns].null? ? nil : Namespace.wrap(cstruct.document, cstruct[:ns])
134
+ end
135
+
136
+ def namespace_definitions # :nodoc:
137
+ list = []
138
+ ns_ptr = cstruct[:nsDef]
139
+ return list if ns_ptr.null?
140
+ while ! ns_ptr.null?
141
+ ns = Namespace.wrap(cstruct.document, ns_ptr)
142
+ list << ns
143
+ ns_ptr = ns.cstruct[:next]
144
+ end
145
+ list
146
+ end
147
+
148
+ def node_type # :nodoc:
149
+ cstruct[:type]
150
+ end
151
+
152
+ def native_content=(content) # :nodoc:
153
+ LibXML.xmlNodeSetContent(cstruct, content)
154
+ content
155
+ end
156
+
157
+ def content # :nodoc:
158
+ content_ptr = LibXML.xmlNodeGetContent(cstruct)
159
+ return nil if content_ptr.null?
160
+ content = content_ptr.read_string # TODO: encoding?
161
+ LibXML.xmlFree(content_ptr)
162
+ content
163
+ end
164
+
165
+ def add_child(child) # :nodoc:
166
+ Node.reparent_node_with(child, self) do |child_cstruct, my_cstruct|
167
+ LibXML.xmlAddChild(my_cstruct, child_cstruct)
168
+ end
169
+ end
170
+
171
+ def parent # :nodoc:
172
+ cstruct_node_from :parent
173
+ end
174
+
175
+ def node_name=(string) # :nodoc:
176
+ LibXML.xmlNodeSetName(cstruct, string)
177
+ string
178
+ end
179
+
180
+ def node_name # :nodoc:
181
+ cstruct[:name] # TODO: encoding?
182
+ end
183
+
184
+ def path # :nodoc:
185
+ path_ptr = LibXML.xmlGetNodePath(cstruct)
186
+ val = path_ptr.null? ? nil : path_ptr.read_string # TODO: encoding?
187
+ LibXML.xmlFree(path_ptr)
188
+ val
189
+ end
190
+
191
+ def add_next_sibling(next_sibling) # :nodoc:
192
+ Node.reparent_node_with(next_sibling, self) do |sibling_cstruct, my_cstruct|
193
+ LibXML.xmlAddNextSibling(my_cstruct, sibling_cstruct)
194
+ end
195
+ end
196
+
197
+ def add_previous_sibling(prev_sibling) # :nodoc:
198
+ Node.reparent_node_with(prev_sibling, self) do |sibling_cstruct, my_cstruct|
199
+ LibXML.xmlAddPrevSibling(my_cstruct, sibling_cstruct)
200
+ end
201
+ end
202
+
203
+ def native_write_to(io, encoding, indent_string, options) # :nodoc:
204
+ set_xml_indent_tree_output 1
205
+ set_xml_tree_indent_string indent_string
206
+ savectx = LibXML.xmlSaveToIO(IoCallbacks.writer(io), nil, nil, encoding, options)
207
+ LibXML.xmlSaveTree(savectx, cstruct)
208
+ LibXML.xmlSaveClose(savectx)
209
+ io
210
+ end
211
+
212
+ def line # :nodoc:
213
+ cstruct[:line]
214
+ end
215
+
216
+ def add_namespace_definition(prefix, href) # :nodoc:
217
+ ns = LibXML.xmlNewNs(cstruct, href, prefix)
218
+ LibXML.xmlSetNs(cstruct, ns) if prefix.nil?
219
+ Namespace.wrap(cstruct.document, ns)
220
+ end
221
+
222
+ def self.new(name, document, *rest) # :nodoc:
223
+ ptr = LibXML.xmlNewNode(nil, name.to_s)
224
+
225
+ node_cstruct = LibXML::XmlNode.new(ptr)
226
+ node_cstruct[:doc] = document.cstruct[:doc]
227
+ node_cstruct.keep_reference_from_document!
228
+
229
+ node = Node.wrap(node_cstruct, self)
230
+ node.send :initialize, name, document, *rest
231
+ yield node if block_given?
232
+ node
233
+ end
234
+
235
+ def dump_html # :nodoc:
236
+ return to_xml if type == DOCUMENT_NODE
237
+ buffer = LibXML::XmlBuffer.new(LibXML.xmlBufferCreate())
238
+ LibXML.htmlNodeDump(buffer, cstruct[:doc], cstruct)
239
+ buffer[:content] # TODO: encoding?
240
+ end
241
+
242
+ def compare(other) # :nodoc:
243
+ LibXML.xmlXPathCmpNodes(other.cstruct, self.cstruct)
244
+ end
245
+
246
+ def self.wrap(node_struct, klass=nil) # :nodoc:
247
+ if node_struct.is_a?(FFI::Pointer)
248
+ # cast native pointers up into a node cstruct
249
+ return nil if node_struct.null?
250
+ node_struct = LibXML::XmlNode.new(node_struct)
251
+ end
252
+
253
+ raise "wrapping a node without a document" unless node_struct.document
254
+
255
+ document_struct = node_struct.document
256
+ document = document_struct.nil? ? nil : document_struct.ruby_doc
257
+ if node_struct[:type] == DOCUMENT_NODE || node_struct[:type] == HTML_DOCUMENT_NODE
258
+ return document
259
+ end
260
+
261
+ ruby_node = node_struct.ruby_node
262
+ return ruby_node unless ruby_node.nil?
263
+
264
+ klasses = case node_struct[:type]
265
+ when ELEMENT_NODE then [XML::Element]
266
+ when TEXT_NODE then [XML::Text]
267
+ when ENTITY_REF_NODE then [XML::EntityReference]
268
+ when COMMENT_NODE then [XML::Comment]
269
+ when DOCUMENT_FRAG_NODE then [XML::DocumentFragment]
270
+ when PI_NODE then [XML::ProcessingInstruction]
271
+ when ATTRIBUTE_NODE then [XML::Attr]
272
+ when ENTITY_DECL then [XML::EntityDeclaration]
273
+ when CDATA_SECTION_NODE then [XML::CDATA]
274
+ when DTD_NODE then [XML::DTD, LibXML::XmlDtd]
275
+ else [XML::Node]
276
+ end
277
+
278
+ if klass
279
+ node = klass.allocate
280
+ else
281
+ node = klasses.first.allocate
282
+ end
283
+ node.cstruct = klasses[1] ? klasses[1].new(node_struct.pointer) : node_struct
284
+
285
+ node.cstruct.ruby_node = node
286
+
287
+ cache = document.instance_variable_get(:@node_cache)
288
+ cache << node
289
+
290
+ node.instance_variable_set(:@document, document)
291
+ document.decorate(node)
292
+ node
293
+ end
294
+
295
+ def document
296
+ cstruct.document.ruby_doc
297
+ end
298
+
299
+ private
300
+
301
+ def self.reparent_node_with(node, other, &block) # :nodoc:
302
+ raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(Nokogiri::XML::Node)
303
+
304
+ if node.cstruct[:doc] == other.cstruct[:doc]
305
+ LibXML.xmlUnlinkNode(node.cstruct)
306
+ if node.type == TEXT_NODE && other.type == TEXT_NODE && Nokogiri.is_2_6_16?
307
+ other.cstruct.pointer.put_pointer(other.cstruct.offset_of(:content), LibXML.xmlStrdup(other.cstruct[:content]))
308
+ end
309
+ reparented_struct = block.call(node.cstruct, other.cstruct)
310
+ raise(RuntimeError, "Could not reparent node (1)") unless reparented_struct
311
+ else
312
+ duped_node = LibXML.xmlDocCopyNode(node.cstruct, other.cstruct.document, 1)
313
+ raise(RuntimeError, "Could not reparent node (xmlDocCopyNode)") unless duped_node
314
+ reparented_struct = block.call(duped_node, other.cstruct)
315
+ raise(RuntimeError, "Could not reparent node (2)") unless reparented_struct
316
+ LibXML.xmlUnlinkNode(node.cstruct)
317
+ node.cstruct.keep_reference_from_document!
318
+ end
319
+
320
+ reparented_struct = LibXML::XmlNode.new(reparented_struct)
321
+
322
+ # the child was a text node that was coalesced. we need to have the object
323
+ # point at SOMETHING, or we'll totally bomb out.
324
+ if reparented_struct != node.cstruct
325
+ node.cstruct = reparented_struct
326
+ end
327
+
328
+ relink_namespace reparented_struct
329
+
330
+ reparented = Node.wrap(reparented_struct)
331
+ reparented.decorate!
332
+ reparented
333
+ end
334
+
335
+ def self.relink_namespace(reparented_struct) # :nodoc:
336
+ # Make sure that our reparented node has the correct namespaces
337
+ if reparented_struct[:doc] != reparented_struct[:parent]
338
+ LibXML.xmlSetNs(reparented_struct, LibXML::XmlNode.new(reparented_struct[:parent])[:ns])
339
+ end
340
+
341
+ # Search our parents for an existing definition
342
+ if ! reparented_struct[:nsDef].null?
343
+ ns = LibXML.xmlSearchNsByHref(
344
+ reparented_struct[:doc],
345
+ reparented_struct[:parent],
346
+ LibXML::XmlNs.new(reparented_struct[:nsDef])[:href]
347
+ )
348
+ reparented_struct[:nsDef] = nil unless ns.null?
349
+ end
350
+
351
+ # Only walk all children if there actually is a namespace we need to reparent.
352
+ return if reparented_struct[:ns].null?
353
+
354
+ # When a node gets reparented, walk it's children to make sure that
355
+ # their namespaces are reparented as well.
356
+ child_ptr = reparented_struct[:children]
357
+ while ! child_ptr.null?
358
+ child_struct = LibXML::XmlNode.new(child_ptr)
359
+ relink_namespace child_struct
360
+ child_ptr = child_struct[:next]
361
+ end
362
+ end
363
+
364
+ def cstruct_node_from(sym) # :nodoc:
365
+ (val = cstruct[sym]).null? ? nil : Node.wrap(val)
366
+ end
367
+
368
+ def set_xml_indent_tree_output(value) # :nodoc:
369
+ LibXML.__xmlIndentTreeOutput.write_int(value)
370
+ end
371
+
372
+ def set_xml_tree_indent_string(value) # :nodoc:
373
+ LibXML.__xmlTreeIndentString.write_pointer(LibXML.xmlStrdup(value.to_s))
374
+ end
375
+
376
+ end
377
+ end
378
+ end
379
+
380
+ class Nokogiri::XML::Element < Nokogiri::XML::Node ; end
@@ -0,0 +1,130 @@
1
+ module Nokogiri
2
+ module XML
3
+ class NodeSet
4
+
5
+ attr_accessor :cstruct # :nodoc:
6
+
7
+ def dup # :nodoc:
8
+ dup = LibXML.xmlXPathNodeSetMerge(nil, self.cstruct)
9
+ NodeSet.wrap(dup)
10
+ end
11
+
12
+ def length # :nodoc:
13
+ cstruct.pointer.null? ? 0 : cstruct[:nodeNr]
14
+ end
15
+
16
+ def push(node) # :nodoc:
17
+ raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node)
18
+ LibXML.xmlXPathNodeSetAdd(cstruct, node.cstruct)
19
+ self
20
+ end
21
+
22
+ def +(node_set) # :nodoc:
23
+ raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet)
24
+ new_set_ptr = LibXML::xmlXPathNodeSetMerge(nil, self.cstruct)
25
+ new_set_ptr = LibXML::xmlXPathNodeSetMerge(new_set_ptr, node_set.cstruct)
26
+ NodeSet.wrap(new_set_ptr)
27
+ end
28
+
29
+ def -(node_set) # :nodoc:
30
+ raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet)
31
+ new_set_ptr = LibXML.xmlXPathNodeSetMerge(nil, self.cstruct)
32
+
33
+ other_nodetab = node_set.cstruct.nodeTab
34
+ node_set.cstruct[:nodeNr].times do |j|
35
+ LibXML.xmlXPathNodeSetDel(new_set_ptr, other_nodetab[j])
36
+ end
37
+ NodeSet.wrap(new_set_ptr)
38
+ end
39
+
40
+ def delete(node) # :nodoc:
41
+ raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node)
42
+ if LibXML.xmlXPathNodeSetContains(cstruct, node.cstruct) != 0
43
+ LibXML.xmlXPathNodeSetDel(cstruct, node.cstruct)
44
+ return node
45
+ end
46
+ return nil
47
+ end
48
+
49
+ def [](*args) # :nodoc:
50
+ raise(ArgumentError, "got #{args.length} arguments, expected 1 (or 2)") if args.length > 2
51
+
52
+ if args.length == 2
53
+ beg = args[0]
54
+ len = args[1]
55
+ beg += cstruct[:nodeNr] if beg < 0
56
+ return subseq(beg, len)
57
+ end
58
+ arg = args[0]
59
+
60
+ return subseq(arg.first, arg.last-arg.first+1) if arg.is_a?(Range)
61
+
62
+ index_at(arg)
63
+ end
64
+ alias_method :slice, :[]
65
+
66
+ def &(node_set) # :nodoc:
67
+ raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet)
68
+ new_set_ptr = LibXML.xmlXPathIntersection(cstruct, node_set.cstruct)
69
+ NodeSet.wrap(new_set_ptr)
70
+ end
71
+
72
+ def include?(node) # :nodoc:
73
+ raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node)
74
+ (LibXML.xmlXPathNodeSetContains(cstruct, node.cstruct) != 0) ? true : false
75
+ end
76
+
77
+ def to_a # :nodoc:
78
+ cstruct.nodeTab.collect { |node| Node.wrap(node) }
79
+ end
80
+
81
+ def unlink # :nodoc:
82
+ # TODO: is this simpler implementation viable:
83
+ # cstruct.nodeTab.collect {|node| Node.wrap(node)}.each(&:unlink)
84
+ # ?
85
+ nodetab = cstruct.nodeTab
86
+ cstruct[:nodeNr].times do |j|
87
+ node = Node.wrap(nodetab[j])
88
+ node.unlink
89
+ nodetab[j] = node.cstruct.pointer
90
+ end
91
+ cstruct.nodeTab = nodetab
92
+ self
93
+ end
94
+
95
+ def self.new document, list = [] # :nodoc:
96
+ set = NodeSet.wrap(LibXML.xmlXPathNodeSetCreate(nil))
97
+ set.document = document
98
+ list.each { |x| set << x }
99
+ yield set if block_given?
100
+ set
101
+ end
102
+
103
+ private
104
+
105
+ def self.wrap(ptr) # :nodoc:
106
+ set = allocate
107
+ set.cstruct = LibXML::XmlNodeSet.new(ptr)
108
+ set
109
+ end
110
+
111
+ def index_at(number) # :nodoc:
112
+ return nil if (number >= cstruct[:nodeNr] || number.abs > cstruct[:nodeNr])
113
+ number = number + cstruct[:nodeNr] if number < 0
114
+ Node.wrap(cstruct.nodeAt(number))
115
+ end
116
+
117
+ def subseq(beg, len) # :nodoc:
118
+ return nil if beg > cstruct[:nodeNr]
119
+ return nil if beg < 0 || len < 0
120
+
121
+ set = NodeSet.wrap(LibXML.xmlXPathNodeSetCreate(nil))
122
+ beg.upto(beg+len-1) do |j|
123
+ LibXML.xmlXPathNodeSetAdd(set.cstruct, cstruct.nodeAt(j));
124
+ end
125
+ set
126
+ end
127
+
128
+ end
129
+ end
130
+ end