libxml-ruby 2.8.0 → 3.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY +859 -775
  3. data/LICENSE +20 -20
  4. data/MANIFEST +166 -166
  5. data/README.rdoc +217 -184
  6. data/Rakefile +98 -78
  7. data/ext/libxml/extconf.rb +61 -116
  8. data/ext/libxml/libxml.c +80 -76
  9. data/ext/libxml/ruby_libxml.h +67 -75
  10. data/ext/libxml/ruby_xml.c +937 -893
  11. data/ext/libxml/ruby_xml.h +10 -10
  12. data/ext/libxml/ruby_xml_attr.c +333 -333
  13. data/ext/libxml/ruby_xml_attr.h +12 -12
  14. data/ext/libxml/ruby_xml_attr_decl.c +153 -153
  15. data/ext/libxml/ruby_xml_attr_decl.h +11 -11
  16. data/ext/libxml/ruby_xml_attributes.c +275 -275
  17. data/ext/libxml/ruby_xml_attributes.h +15 -15
  18. data/ext/libxml/ruby_xml_cbg.c +85 -85
  19. data/ext/libxml/ruby_xml_document.c +1123 -1147
  20. data/ext/libxml/ruby_xml_document.h +11 -11
  21. data/ext/libxml/ruby_xml_dtd.c +248 -268
  22. data/ext/libxml/ruby_xml_dtd.h +9 -9
  23. data/ext/libxml/ruby_xml_encoding.c +250 -260
  24. data/ext/libxml/ruby_xml_encoding.h +16 -19
  25. data/ext/libxml/ruby_xml_error.c +996 -996
  26. data/ext/libxml/ruby_xml_error.h +12 -12
  27. data/ext/libxml/ruby_xml_html_parser.c +89 -92
  28. data/ext/libxml/ruby_xml_html_parser.h +10 -10
  29. data/ext/libxml/ruby_xml_html_parser_context.c +337 -338
  30. data/ext/libxml/ruby_xml_html_parser_context.h +10 -10
  31. data/ext/libxml/ruby_xml_html_parser_options.c +46 -46
  32. data/ext/libxml/ruby_xml_html_parser_options.h +10 -10
  33. data/ext/libxml/ruby_xml_input_cbg.c +191 -191
  34. data/ext/libxml/ruby_xml_input_cbg.h +20 -20
  35. data/ext/libxml/ruby_xml_io.c +47 -50
  36. data/ext/libxml/ruby_xml_io.h +10 -10
  37. data/ext/libxml/ruby_xml_namespace.c +154 -153
  38. data/ext/libxml/ruby_xml_namespace.h +10 -10
  39. data/ext/libxml/ruby_xml_namespaces.c +293 -293
  40. data/ext/libxml/ruby_xml_namespaces.h +9 -9
  41. data/ext/libxml/ruby_xml_node.c +1406 -1452
  42. data/ext/libxml/ruby_xml_node.h +13 -11
  43. data/ext/libxml/ruby_xml_parser.c +91 -94
  44. data/ext/libxml/ruby_xml_parser.h +12 -12
  45. data/ext/libxml/ruby_xml_parser_context.c +999 -1001
  46. data/ext/libxml/ruby_xml_parser_context.h +10 -10
  47. data/ext/libxml/ruby_xml_parser_options.c +66 -66
  48. data/ext/libxml/ruby_xml_parser_options.h +12 -12
  49. data/ext/libxml/ruby_xml_reader.c +1239 -1228
  50. data/ext/libxml/ruby_xml_reader.h +17 -17
  51. data/ext/libxml/ruby_xml_relaxng.c +110 -111
  52. data/ext/libxml/ruby_xml_relaxng.h +10 -10
  53. data/ext/libxml/ruby_xml_sax2_handler.c +326 -328
  54. data/ext/libxml/ruby_xml_sax2_handler.h +10 -10
  55. data/ext/libxml/ruby_xml_sax_parser.c +116 -120
  56. data/ext/libxml/ruby_xml_sax_parser.h +10 -10
  57. data/ext/libxml/ruby_xml_schema.c +350 -301
  58. data/ext/libxml/ruby_xml_schema.h +806 -809
  59. data/ext/libxml/ruby_xml_schema_attribute.c +61 -109
  60. data/ext/libxml/ruby_xml_schema_attribute.h +15 -15
  61. data/ext/libxml/ruby_xml_schema_element.c +69 -94
  62. data/ext/libxml/ruby_xml_schema_element.h +14 -14
  63. data/ext/libxml/ruby_xml_schema_facet.c +46 -52
  64. data/ext/libxml/ruby_xml_schema_facet.h +13 -13
  65. data/ext/libxml/ruby_xml_schema_type.c +214 -259
  66. data/ext/libxml/ruby_xml_schema_type.h +9 -9
  67. data/ext/libxml/ruby_xml_version.h +9 -9
  68. data/ext/libxml/ruby_xml_writer.c +1133 -1137
  69. data/ext/libxml/ruby_xml_writer.h +10 -10
  70. data/ext/libxml/ruby_xml_xinclude.c +16 -16
  71. data/ext/libxml/ruby_xml_xinclude.h +11 -11
  72. data/ext/libxml/ruby_xml_xpath.c +194 -188
  73. data/ext/libxml/ruby_xml_xpath.h +13 -13
  74. data/ext/libxml/ruby_xml_xpath_context.c +360 -361
  75. data/ext/libxml/ruby_xml_xpath_context.h +9 -9
  76. data/ext/libxml/ruby_xml_xpath_expression.c +81 -81
  77. data/ext/libxml/ruby_xml_xpath_expression.h +10 -10
  78. data/ext/libxml/ruby_xml_xpath_object.c +338 -335
  79. data/ext/libxml/ruby_xml_xpath_object.h +17 -17
  80. data/ext/libxml/ruby_xml_xpointer.c +99 -99
  81. data/ext/libxml/ruby_xml_xpointer.h +11 -11
  82. data/ext/vc/libxml_ruby.sln +17 -15
  83. data/lib/libxml/node.rb +2 -78
  84. data/lib/libxml/parser.rb +0 -266
  85. data/lib/libxml/sax_parser.rb +0 -17
  86. data/lib/libxml/schema/attribute.rb +19 -19
  87. data/lib/libxml/schema/element.rb +19 -27
  88. data/lib/libxml/schema/type.rb +21 -29
  89. data/lib/libxml/schema.rb +47 -66
  90. data/lib/libxml-ruby.rb +30 -0
  91. data/lib/libxml.rb +3 -33
  92. data/libxml-ruby.gemspec +48 -44
  93. data/script/benchmark/depixelate +634 -634
  94. data/script/benchmark/hamlet.xml +9054 -9054
  95. data/script/benchmark/parsecount +170 -170
  96. data/script/benchmark/throughput +41 -41
  97. data/script/test +6 -6
  98. data/setup.rb +0 -1
  99. data/test/c14n/given/example-1.xml +14 -14
  100. data/test/c14n/given/example-2.xml +11 -11
  101. data/test/c14n/given/example-3.xml +18 -18
  102. data/test/c14n/given/example-4.xml +9 -9
  103. data/test/c14n/given/example-5.xml +12 -12
  104. data/test/c14n/given/example-6.xml +2 -2
  105. data/test/c14n/given/example-7.xml +11 -11
  106. data/test/c14n/given/example-8.xml +11 -11
  107. data/test/c14n/given/example-8.xpath +9 -9
  108. data/test/c14n/result/1-1-without-comments/example-1 +3 -3
  109. data/test/c14n/result/1-1-without-comments/example-2 +10 -10
  110. data/test/c14n/result/1-1-without-comments/example-3 +13 -13
  111. data/test/c14n/result/1-1-without-comments/example-4 +8 -8
  112. data/test/c14n/result/1-1-without-comments/example-5 +2 -2
  113. data/test/c14n/result/with-comments/example-1 +5 -5
  114. data/test/c14n/result/with-comments/example-2 +10 -10
  115. data/test/c14n/result/with-comments/example-3 +13 -13
  116. data/test/c14n/result/with-comments/example-4 +8 -8
  117. data/test/c14n/result/with-comments/example-5 +3 -3
  118. data/test/c14n/result/without-comments/example-1 +3 -3
  119. data/test/c14n/result/without-comments/example-2 +10 -10
  120. data/test/c14n/result/without-comments/example-3 +13 -13
  121. data/test/c14n/result/without-comments/example-4 +8 -8
  122. data/test/c14n/result/without-comments/example-5 +2 -2
  123. data/test/model/atom.xml +12 -12
  124. data/test/model/bands.iso-8859-1.xml +4 -4
  125. data/test/model/bands.utf-8.xml +4 -4
  126. data/test/model/bands.xml +4 -4
  127. data/test/model/books.xml +153 -153
  128. data/test/model/cwm_1_0.xml +11336 -0
  129. data/test/model/merge_bug_data.xml +58 -58
  130. data/test/model/ruby-lang.html +238 -238
  131. data/test/model/rubynet.xml +79 -79
  132. data/test/model/shiporder.rnc +28 -28
  133. data/test/model/shiporder.rng +86 -86
  134. data/test/model/shiporder.xml +22 -22
  135. data/test/model/shiporder.xsd +44 -40
  136. data/test/model/shiporder_bad.xsd +40 -0
  137. data/test/model/shiporder_import.xsd +45 -0
  138. data/test/model/soap.xml +27 -27
  139. data/test/model/xinclude.xml +4 -4
  140. data/test/{tc_attr.rb → test_attr.rb} +23 -25
  141. data/test/{tc_attr_decl.rb → test_attr_decl.rb} +13 -14
  142. data/test/{tc_attributes.rb → test_attributes.rb} +11 -18
  143. data/test/{tc_canonicalize.rb → test_canonicalize.rb} +36 -41
  144. data/test/test_deprecated_require.rb +12 -0
  145. data/test/{tc_document.rb → test_document.rb} +33 -27
  146. data/test/test_document_write.rb +146 -0
  147. data/test/{tc_dtd.rb → test_dtd.rb} +29 -29
  148. data/test/{tc_encoding.rb → test_encoding.rb} +129 -126
  149. data/test/{tc_encoding_sax.rb → test_encoding_sax.rb} +7 -6
  150. data/test/test_error.rb +178 -0
  151. data/test/test_helper.rb +4 -9
  152. data/test/test_html_parser.rb +162 -0
  153. data/test/test_html_parser_context.rb +23 -0
  154. data/test/test_namespace.rb +60 -0
  155. data/test/{tc_namespaces.rb → test_namespaces.rb} +34 -44
  156. data/test/{tc_node.rb → test_node.rb} +68 -47
  157. data/test/{tc_node_cdata.rb → test_node_cdata.rb} +12 -13
  158. data/test/{tc_node_comment.rb → test_node_comment.rb} +7 -8
  159. data/test/{tc_node_copy.rb → test_node_copy.rb} +4 -6
  160. data/test/{tc_node_edit.rb → test_node_edit.rb} +23 -41
  161. data/test/{tc_node_pi.rb → test_node_pi.rb} +37 -40
  162. data/test/{tc_node_text.rb → test_node_text.rb} +10 -12
  163. data/test/{tc_node_write.rb → test_node_write.rb} +18 -29
  164. data/test/test_node_xlink.rb +28 -0
  165. data/test/test_parser.rb +324 -0
  166. data/test/{tc_parser_context.rb → test_parser_context.rb} +42 -49
  167. data/test/{tc_properties.rb → test_properties.rb} +6 -7
  168. data/test/test_reader.rb +364 -0
  169. data/test/test_relaxng.rb +53 -0
  170. data/test/{tc_sax_parser.rb → test_sax_parser.rb} +44 -38
  171. data/test/test_schema.rb +231 -0
  172. data/test/test_suite.rb +38 -40
  173. data/test/{tc_traversal.rb → test_traversal.rb} +5 -6
  174. data/test/{tc_writer.rb → test_writer.rb} +468 -448
  175. data/test/{tc_xinclude.rb → test_xinclude.rb} +4 -5
  176. data/test/test_xml.rb +263 -0
  177. data/test/{tc_xpath.rb → test_xpath.rb} +31 -32
  178. data/test/{tc_xpath_context.rb → test_xpath_context.rb} +8 -9
  179. data/test/test_xpath_expression.rb +37 -0
  180. data/test/{tc_xpointer.rb → test_xpointer.rb} +16 -18
  181. metadata +122 -100
  182. data/lib/libxml/ns.rb +0 -22
  183. data/lib/libxml/properties.rb +0 -23
  184. data/lib/libxml/reader.rb +0 -29
  185. data/lib/libxml/xpath_object.rb +0 -16
  186. data/test/etc_doc_to_s.rb +0 -21
  187. data/test/ets_doc_file.rb +0 -17
  188. data/test/ets_doc_to_s.rb +0 -23
  189. data/test/ets_gpx.rb +0 -28
  190. data/test/ets_node_gc.rb +0 -23
  191. data/test/ets_test.xml +0 -2
  192. data/test/ets_tsr.rb +0 -11
  193. data/test/tc_deprecated_require.rb +0 -13
  194. data/test/tc_document_write.rb +0 -196
  195. data/test/tc_error.rb +0 -180
  196. data/test/tc_html_parser.rb +0 -153
  197. data/test/tc_html_parser_context.rb +0 -24
  198. data/test/tc_namespace.rb +0 -62
  199. data/test/tc_node_xlink.rb +0 -29
  200. data/test/tc_parser.rb +0 -381
  201. data/test/tc_reader.rb +0 -400
  202. data/test/tc_relaxng.rb +0 -54
  203. data/test/tc_schema.rb +0 -162
  204. data/test/tc_xml.rb +0 -226
  205. data/test/tc_xpath_expression.rb +0 -38
@@ -1,361 +1,360 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- #include "ruby_libxml.h"
4
- #include "ruby_xml_xpath_context.h"
5
- #include "ruby_xml_xpath_expression.h"
6
-
7
- #if RUBY_ST_H
8
- #include <ruby/st.h>
9
- #else
10
- #include <st.h>
11
- #endif
12
-
13
- /*
14
- * Document-class: LibXML::XML::XPath::Context
15
- *
16
- * The XML::XPath::Context class is used to evaluate XPath
17
- * expressions. Generally, you should not directly use this class,
18
- * but instead use the XML::Document#find and XML::Node#find methods.
19
- *
20
- * doc = XML::Document.string('<header>content</header>')
21
- * context = XPath::Context.new(doc)
22
- * context.node = doc.root
23
- * context.register_namespaces_from_node(doc.root)
24
- * nodes = context.find('/header')
25
- */
26
-
27
- VALUE cXMLXPathContext;
28
-
29
- static void rxml_xpath_context_free(xmlXPathContextPtr ctxt)
30
- {
31
- xmlXPathFreeContext(ctxt);
32
- }
33
-
34
- static void rxml_xpath_context_mark(xmlXPathContextPtr ctxt)
35
- {
36
- if (ctxt && ctxt->doc->_private)
37
- rb_gc_mark((VALUE) ctxt->doc->_private);
38
- }
39
-
40
- static VALUE rxml_xpath_context_alloc(VALUE klass)
41
- {
42
- return Data_Wrap_Struct(cXMLXPathContext, rxml_xpath_context_mark, rxml_xpath_context_free, NULL);
43
- }
44
-
45
- /* call-seq:
46
- * XPath::Context.new(doc) -> XPath::Context
47
- *
48
- * Creates a new XPath context for the specified document. The
49
- * context can then be used to evaluate an XPath expression.
50
- *
51
- * doc = XML::Document.string('<header><first>hi</first></header>')
52
- * context = XPath::Context.new(doc)
53
- * nodes = XPath::Object.new('//first', context)
54
- * nodes.length == 1
55
- */
56
- static VALUE rxml_xpath_context_initialize(VALUE self, VALUE document)
57
- {
58
- xmlDocPtr xdoc;
59
-
60
- if (rb_obj_is_kind_of(document, cXMLDocument) != Qtrue)
61
- {
62
- rb_raise(rb_eTypeError, "Supplied argument must be a document or node.");
63
- }
64
-
65
- Data_Get_Struct(document, xmlDoc, xdoc);
66
- DATA_PTR(self) = xmlXPathNewContext(xdoc);
67
-
68
- return self;
69
- }
70
-
71
- /*
72
- * call-seq:
73
- * context.doc -> document
74
- *
75
- * Obtain the XML::Document this node belongs to.
76
- */
77
- static VALUE rxml_xpath_context_doc(VALUE self)
78
- {
79
- xmlDocPtr xdoc = NULL;
80
- xmlXPathContextPtr ctxt;
81
- Data_Get_Struct(self, xmlXPathContext, ctxt);
82
-
83
- xdoc = ctxt->doc;
84
- return rxml_document_wrap(xdoc);
85
- }
86
-
87
- /*
88
- * call-seq:
89
- * context.register_namespace(prefix, uri) -> (true|false)
90
- *
91
- * Register the specified namespace URI with the specified prefix
92
- * in this context.
93
-
94
- * context.register_namespace('xi', 'http://www.w3.org/2001/XInclude')
95
- */
96
- static VALUE rxml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri)
97
- {
98
- xmlXPathContextPtr ctxt;
99
- Data_Get_Struct(self, xmlXPathContext, ctxt);
100
-
101
- /* Prefix could be a symbol. */
102
- prefix = rb_obj_as_string(prefix);
103
-
104
- if (xmlXPathRegisterNs(ctxt, (xmlChar*) StringValuePtr(prefix),
105
- (xmlChar*) StringValuePtr(uri)) == 0)
106
- {
107
- return (Qtrue);
108
- }
109
- else
110
- {
111
- /* Should raise an exception, IMHO (whose?, why shouldnt it? -danj)*/
112
- rb_warning("register namespace failed");
113
- return (Qfalse);
114
- }
115
- }
116
-
117
- /* call-seq:
118
- * context.register_namespaces_from_node(node) -> self
119
- *
120
- * Helper method to read in namespaces defined on a node.
121
- *
122
- * doc = XML::Document.string('<header><first>hi</first></header>')
123
- * context = XPath::Context.new(doc)
124
- * context.register_namespaces_from_node(doc.root)
125
- */
126
- static VALUE rxml_xpath_context_register_namespaces_from_node(VALUE self,
127
- VALUE node)
128
- {
129
- xmlXPathContextPtr xctxt;
130
- xmlNodePtr xnode;
131
- xmlNsPtr *xnsArr;
132
-
133
- Data_Get_Struct(self, xmlXPathContext, xctxt);
134
-
135
- if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
136
- {
137
- xmlDocPtr xdoc;
138
- Data_Get_Struct(node, xmlDoc, xdoc);
139
- xnode = xmlDocGetRootElement(xdoc);
140
- }
141
- else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
142
- {
143
- Data_Get_Struct(node, xmlNode, xnode);
144
- }
145
- else
146
- {
147
- rb_raise(rb_eTypeError, "The first argument must be a document or node.");
148
- }
149
-
150
- xnsArr = xmlGetNsList(xnode->doc, xnode);
151
-
152
- if (xnsArr)
153
- {
154
- xmlNsPtr xns = *xnsArr;
155
-
156
- while (xns)
157
- {
158
- /* If there is no prefix, then this is the default namespace.
159
- Skip it for now. */
160
- if (xns->prefix)
161
- {
162
- VALUE prefix = rxml_new_cstr((const char*)xns->prefix, xctxt->doc->encoding);
163
- VALUE uri = rxml_new_cstr((const char*)xns->href, xctxt->doc->encoding);
164
- rxml_xpath_context_register_namespace(self, prefix, uri);
165
- }
166
- xns = xns->next;
167
- }
168
- xmlFree(xnsArr);
169
- }
170
-
171
- return self;
172
- }
173
-
174
- static int iterate_ns_hash(VALUE prefix, VALUE uri, VALUE self)
175
- {
176
- rxml_xpath_context_register_namespace(self, prefix, uri);
177
- return ST_CONTINUE;
178
- }
179
-
180
- /*
181
- * call-seq:
182
- * context.register_namespaces(["prefix:uri"]) -> self
183
- *
184
- * Register the specified namespaces in this context. There are
185
- * three different forms that libxml accepts. These include
186
- * a string, an array of strings, or a hash table:
187
- *
188
- * context.register_namespaces('xi:http://www.w3.org/2001/XInclude')
189
- * context.register_namespaces(['xlink:http://www.w3.org/1999/xlink',
190
- * 'xi:http://www.w3.org/2001/XInclude')
191
- * context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink',
192
- * 'xi' => 'http://www.w3.org/2001/XInclude')
193
- */
194
- static VALUE rxml_xpath_context_register_namespaces(VALUE self, VALUE nslist)
195
- {
196
- char *cp;
197
- long i;
198
- VALUE rprefix, ruri;
199
- xmlXPathContextPtr xctxt;
200
-
201
- Data_Get_Struct(self, xmlXPathContext, xctxt);
202
-
203
- /* Need to loop through the 2nd argument and iterate through the
204
- * list of namespaces that we want to allow */
205
- switch (TYPE(nslist))
206
- {
207
- case T_STRING:
208
- cp = strchr(StringValuePtr(nslist), (int) ':');
209
- if (cp == NULL)
210
- {
211
- rprefix = nslist;
212
- ruri = Qnil;
213
- }
214
- else
215
- {
216
- rprefix = rb_str_new(StringValuePtr(nslist), (int) ((long) cp
217
- - (long) StringValuePtr(nslist)));
218
- ruri = rxml_new_cstr(&cp[1], xctxt->doc->encoding);
219
- }
220
- /* Should test the results of this */
221
- rxml_xpath_context_register_namespace(self, rprefix, ruri);
222
- break;
223
- case T_ARRAY:
224
- for (i = 0; i < RARRAY_LEN(nslist); i++)
225
- {
226
- rxml_xpath_context_register_namespaces(self, RARRAY_PTR(nslist)[i]);
227
- }
228
- break;
229
- case T_HASH:
230
- rb_hash_foreach(nslist, iterate_ns_hash, self);
231
- break;
232
- default:
233
- rb_raise(
234
- rb_eArgError,
235
- "Invalid argument type, only accept string, array of strings, or an array of arrays");
236
- }
237
- return self;
238
- }
239
-
240
- /*
241
- * call-seq:
242
- * context.node = node
243
- *
244
- * Set the current node used by the XPath engine
245
-
246
- * doc = XML::Document.string('<header><first>hi</first></header>')
247
- * context.node = doc.root.first
248
- */
249
- static VALUE rxml_xpath_context_node_set(VALUE self, VALUE node)
250
- {
251
- xmlXPathContextPtr xctxt;
252
- xmlNodePtr xnode;
253
-
254
- Data_Get_Struct(self, xmlXPathContext, xctxt);
255
- Data_Get_Struct(node, xmlNode, xnode);
256
- xctxt->node = xnode;
257
- return node;
258
- }
259
-
260
- /*
261
- * call-seq:
262
- * context.find("xpath") -> true|false|number|string|XML::XPath::Object
263
- *
264
- * Executes the provided xpath function. The result depends on the execution
265
- * of the xpath statement. It may be true, false, a number, a string or
266
- * a node set.
267
- */
268
- static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
269
- {
270
- xmlXPathContextPtr xctxt;
271
- xmlXPathObjectPtr xobject;
272
- xmlXPathCompExprPtr xcompexpr;
273
-
274
- Data_Get_Struct(self, xmlXPathContext, xctxt);
275
-
276
- if (TYPE(xpath_expr) == T_STRING)
277
- {
278
- VALUE expression = rb_check_string_type(xpath_expr);
279
- xobject = xmlXPathEval((xmlChar*) StringValueCStr(expression), xctxt);
280
- }
281
- else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression))
282
- {
283
- Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr);
284
- xobject = xmlXPathCompiledEval(xcompexpr, xctxt);
285
- }
286
- else
287
- {
288
- rb_raise(rb_eTypeError,
289
- "Argument should be an intance of a String or XPath::Expression");
290
- }
291
-
292
- return rxml_xpath_to_value(xctxt, xobject);
293
- }
294
-
295
- #if LIBXML_VERSION >= 20626
296
- /*
297
- * call-seq:
298
- * context.enable_cache(size = nil)
299
- *
300
- * Enables an XPath::Context's built-in cache. If the cache is
301
- * enabled then XPath objects will be cached internally for reuse.
302
- * The size parameter controls sets the maximum number of XPath objects
303
- * that will be cached per XPath object type (node-set, string, number,
304
- * boolean, and misc objects). Set size to nil to use the default
305
- * cache size of 100.
306
- */
307
- static VALUE
308
- rxml_xpath_context_enable_cache(int argc, VALUE *argv, VALUE self)
309
- {
310
- xmlXPathContextPtr xctxt;
311
- VALUE size;
312
- int value = -1;
313
-
314
- Data_Get_Struct(self, xmlXPathContext, xctxt);
315
-
316
- if (rb_scan_args(argc, argv, "01", &size) == 1)
317
- {
318
- value = NUM2INT(size);
319
- }
320
-
321
- if (xmlXPathContextSetCache(xctxt, 1, value, 0) == -1)
322
- rxml_raise(&xmlLastError);
323
-
324
- return self;
325
- }
326
-
327
- /*
328
- * call-seq:
329
- * context.disable_cache
330
- *
331
- * Disables an XPath::Context's built-in cache.
332
- */
333
- static VALUE
334
- rxml_xpath_context_disable_cache(VALUE self)
335
- {
336
- xmlXPathContextPtr xctxt;
337
- Data_Get_Struct(self, xmlXPathContext, xctxt);
338
-
339
- if (xmlXPathContextSetCache(xctxt, 0, 0, 0) == -1)
340
- rxml_raise(&xmlLastError);
341
-
342
- return self;
343
- }
344
- #endif
345
-
346
- void rxml_init_xpath_context(void)
347
- {
348
- cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
349
- rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
350
- rb_define_method(cXMLXPathContext, "doc", rxml_xpath_context_doc, 0);
351
- rb_define_method(cXMLXPathContext, "initialize", rxml_xpath_context_initialize, 1);
352
- rb_define_method(cXMLXPathContext, "register_namespaces", rxml_xpath_context_register_namespaces, 1);
353
- rb_define_method(cXMLXPathContext, "register_namespaces_from_node", rxml_xpath_context_register_namespaces_from_node, 1);
354
- rb_define_method(cXMLXPathContext, "register_namespace", rxml_xpath_context_register_namespace, 2);
355
- rb_define_method(cXMLXPathContext, "node=", rxml_xpath_context_node_set, 1);
356
- rb_define_method(cXMLXPathContext, "find", rxml_xpath_context_find, 1);
357
- #if LIBXML_VERSION >= 20626
358
- rb_define_method(cXMLXPathContext, "enable_cache", rxml_xpath_context_enable_cache, -1);
359
- rb_define_method(cXMLXPathContext, "disable_cache", rxml_xpath_context_disable_cache, 0);
360
- #endif
361
- }
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #include "ruby_libxml.h"
4
+ #include "ruby_xml_xpath_context.h"
5
+ #include "ruby_xml_xpath_expression.h"
6
+
7
+ #if RUBY_ST_H
8
+ #include <ruby/st.h>
9
+ #else
10
+ #include <st.h>
11
+ #endif
12
+
13
+ /*
14
+ * Document-class: LibXML::XML::XPath::Context
15
+ *
16
+ * The XML::XPath::Context class is used to evaluate XPath
17
+ * expressions. Generally, you should not directly use this class,
18
+ * but instead use the XML::Document#find and XML::Node#find methods.
19
+ *
20
+ * doc = XML::Document.string('<header>content</header>')
21
+ * context = XPath::Context.new(doc)
22
+ * context.node = doc.root
23
+ * context.register_namespaces_from_node(doc.root)
24
+ * nodes = context.find('/header')
25
+ */
26
+
27
+ VALUE cXMLXPathContext;
28
+
29
+ static void rxml_xpath_context_free(xmlXPathContextPtr ctxt)
30
+ {
31
+ xmlXPathFreeContext(ctxt);
32
+ }
33
+
34
+ static void rxml_xpath_context_mark(xmlXPathContextPtr ctxt)
35
+ {
36
+ VALUE value = (VALUE)ctxt->doc->_private;
37
+ rb_gc_mark(value);
38
+ }
39
+
40
+ static VALUE rxml_xpath_context_alloc(VALUE klass)
41
+ {
42
+ return Data_Wrap_Struct(cXMLXPathContext, rxml_xpath_context_mark, rxml_xpath_context_free, NULL);
43
+ }
44
+
45
+ /* call-seq:
46
+ * XPath::Context.new(doc) -> XPath::Context
47
+ *
48
+ * Creates a new XPath context for the specified document. The
49
+ * context can then be used to evaluate an XPath expression.
50
+ *
51
+ * doc = XML::Document.string('<header><first>hi</first></header>')
52
+ * context = XPath::Context.new(doc)
53
+ * nodes = XPath::Object.new('//first', context)
54
+ * nodes.length == 1
55
+ */
56
+ static VALUE rxml_xpath_context_initialize(VALUE self, VALUE document)
57
+ {
58
+ xmlDocPtr xdoc;
59
+
60
+ if (rb_obj_is_kind_of(document, cXMLDocument) != Qtrue)
61
+ {
62
+ rb_raise(rb_eTypeError, "Supplied argument must be a document or node.");
63
+ }
64
+
65
+ Data_Get_Struct(document, xmlDoc, xdoc);
66
+ DATA_PTR(self) = xmlXPathNewContext(xdoc);
67
+
68
+ return self;
69
+ }
70
+
71
+ /*
72
+ * call-seq:
73
+ * context.doc -> document
74
+ *
75
+ * Obtain the XML::Document this node belongs to.
76
+ */
77
+ static VALUE rxml_xpath_context_doc(VALUE self)
78
+ {
79
+ xmlDocPtr xdoc = NULL;
80
+ xmlXPathContextPtr ctxt;
81
+ Data_Get_Struct(self, xmlXPathContext, ctxt);
82
+
83
+ xdoc = ctxt->doc;
84
+ return rxml_document_wrap(xdoc);
85
+ }
86
+
87
+ /*
88
+ * call-seq:
89
+ * context.register_namespace(prefix, uri) -> (true|false)
90
+ *
91
+ * Register the specified namespace URI with the specified prefix
92
+ * in this context.
93
+
94
+ * context.register_namespace('xi', 'http://www.w3.org/2001/XInclude')
95
+ */
96
+ static VALUE rxml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri)
97
+ {
98
+ xmlXPathContextPtr ctxt;
99
+ Data_Get_Struct(self, xmlXPathContext, ctxt);
100
+
101
+ /* Prefix could be a symbol. */
102
+ prefix = rb_obj_as_string(prefix);
103
+
104
+ if (xmlXPathRegisterNs(ctxt, (xmlChar*) StringValuePtr(prefix),
105
+ (xmlChar*) StringValuePtr(uri)) == 0)
106
+ {
107
+ return (Qtrue);
108
+ }
109
+ else
110
+ {
111
+ /* Should raise an exception, IMHO (whose?, why shouldnt it? -danj)*/
112
+ rb_warning("register namespace failed");
113
+ return (Qfalse);
114
+ }
115
+ }
116
+
117
+ /* call-seq:
118
+ * context.register_namespaces_from_node(node) -> self
119
+ *
120
+ * Helper method to read in namespaces defined on a node.
121
+ *
122
+ * doc = XML::Document.string('<header><first>hi</first></header>')
123
+ * context = XPath::Context.new(doc)
124
+ * context.register_namespaces_from_node(doc.root)
125
+ */
126
+ static VALUE rxml_xpath_context_register_namespaces_from_node(VALUE self,
127
+ VALUE node)
128
+ {
129
+ xmlXPathContextPtr xctxt;
130
+ xmlNodePtr xnode;
131
+ xmlNsPtr *xnsArr;
132
+
133
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
134
+
135
+ if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
136
+ {
137
+ xmlDocPtr xdoc;
138
+ Data_Get_Struct(node, xmlDoc, xdoc);
139
+ xnode = xmlDocGetRootElement(xdoc);
140
+ }
141
+ else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
142
+ {
143
+ Data_Get_Struct(node, xmlNode, xnode);
144
+ }
145
+ else
146
+ {
147
+ rb_raise(rb_eTypeError, "The first argument must be a document or node.");
148
+ }
149
+
150
+ xnsArr = xmlGetNsList(xnode->doc, xnode);
151
+
152
+ if (xnsArr)
153
+ {
154
+ xmlNsPtr xns = *xnsArr;
155
+
156
+ while (xns)
157
+ {
158
+ /* If there is no prefix, then this is the default namespace.
159
+ Skip it for now. */
160
+ if (xns->prefix)
161
+ {
162
+ VALUE prefix = rxml_new_cstr(xns->prefix, xctxt->doc->encoding);
163
+ VALUE uri = rxml_new_cstr(xns->href, xctxt->doc->encoding);
164
+ rxml_xpath_context_register_namespace(self, prefix, uri);
165
+ }
166
+ xns = xns->next;
167
+ }
168
+ xmlFree(xnsArr);
169
+ }
170
+
171
+ return self;
172
+ }
173
+
174
+ static int iterate_ns_hash(VALUE prefix, VALUE uri, VALUE self)
175
+ {
176
+ rxml_xpath_context_register_namespace(self, prefix, uri);
177
+ return ST_CONTINUE;
178
+ }
179
+
180
+ /*
181
+ * call-seq:
182
+ * context.register_namespaces(["prefix:uri"]) -> self
183
+ *
184
+ * Register the specified namespaces in this context. There are
185
+ * three different forms that libxml accepts. These include
186
+ * a string, an array of strings, or a hash table:
187
+ *
188
+ * context.register_namespaces('xi:http://www.w3.org/2001/XInclude')
189
+ * context.register_namespaces(['xlink:http://www.w3.org/1999/xlink',
190
+ * 'xi:http://www.w3.org/2001/XInclude')
191
+ * context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink',
192
+ * 'xi' => 'http://www.w3.org/2001/XInclude')
193
+ */
194
+ static VALUE rxml_xpath_context_register_namespaces(VALUE self, VALUE nslist)
195
+ {
196
+ char *cp;
197
+ long i;
198
+ VALUE rprefix, ruri;
199
+ xmlXPathContextPtr xctxt;
200
+
201
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
202
+
203
+ /* Need to loop through the 2nd argument and iterate through the
204
+ * list of namespaces that we want to allow */
205
+ switch (TYPE(nslist))
206
+ {
207
+ case T_STRING:
208
+ cp = strchr(StringValuePtr(nslist), (int) ':');
209
+ if (cp == NULL)
210
+ {
211
+ rprefix = nslist;
212
+ ruri = Qnil;
213
+ }
214
+ else
215
+ {
216
+ rprefix = rb_str_new(StringValuePtr(nslist), (long) ((intptr_t) cp - (intptr_t)StringValuePtr(nslist)));
217
+ ruri = rxml_new_cstr((const xmlChar*)&cp[1], xctxt->doc->encoding);
218
+ }
219
+ /* Should test the results of this */
220
+ rxml_xpath_context_register_namespace(self, rprefix, ruri);
221
+ break;
222
+ case T_ARRAY:
223
+ for (i = 0; i < RARRAY_LEN(nslist); i++)
224
+ {
225
+ rxml_xpath_context_register_namespaces(self, RARRAY_PTR(nslist)[i]);
226
+ }
227
+ break;
228
+ case T_HASH:
229
+ rb_hash_foreach(nslist, iterate_ns_hash, self);
230
+ break;
231
+ default:
232
+ rb_raise(
233
+ rb_eArgError,
234
+ "Invalid argument type, only accept string, array of strings, or an array of arrays");
235
+ }
236
+ return self;
237
+ }
238
+
239
+ /*
240
+ * call-seq:
241
+ * context.node = node
242
+ *
243
+ * Set the current node used by the XPath engine
244
+
245
+ * doc = XML::Document.string('<header><first>hi</first></header>')
246
+ * context.node = doc.root.first
247
+ */
248
+ static VALUE rxml_xpath_context_node_set(VALUE self, VALUE node)
249
+ {
250
+ xmlXPathContextPtr xctxt;
251
+ xmlNodePtr xnode;
252
+
253
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
254
+ Data_Get_Struct(node, xmlNode, xnode);
255
+ xctxt->node = xnode;
256
+ return node;
257
+ }
258
+
259
+ /*
260
+ * call-seq:
261
+ * context.find("xpath") -> true|false|number|string|XML::XPath::Object
262
+ *
263
+ * Executes the provided xpath function. The result depends on the execution
264
+ * of the xpath statement. It may be true, false, a number, a string or
265
+ * a node set.
266
+ */
267
+ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
268
+ {
269
+ xmlXPathContextPtr xctxt;
270
+ xmlXPathObjectPtr xobject;
271
+ xmlXPathCompExprPtr xcompexpr;
272
+
273
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
274
+
275
+ if (TYPE(xpath_expr) == T_STRING)
276
+ {
277
+ VALUE expression = rb_check_string_type(xpath_expr);
278
+ xobject = xmlXPathEval((xmlChar*) StringValueCStr(expression), xctxt);
279
+ }
280
+ else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression))
281
+ {
282
+ Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr);
283
+ xobject = xmlXPathCompiledEval(xcompexpr, xctxt);
284
+ }
285
+ else
286
+ {
287
+ rb_raise(rb_eTypeError,
288
+ "Argument should be an instance of a String or XPath::Expression");
289
+ }
290
+
291
+ return rxml_xpath_to_value(xctxt, xobject);
292
+ }
293
+
294
+ #if LIBXML_VERSION >= 20626
295
+ /*
296
+ * call-seq:
297
+ * context.enable_cache(size = nil)
298
+ *
299
+ * Enables an XPath::Context's built-in cache. If the cache is
300
+ * enabled then XPath objects will be cached internally for reuse.
301
+ * The size parameter controls sets the maximum number of XPath objects
302
+ * that will be cached per XPath object type (node-set, string, number,
303
+ * boolean, and misc objects). Set size to nil to use the default
304
+ * cache size of 100.
305
+ */
306
+ static VALUE
307
+ rxml_xpath_context_enable_cache(int argc, VALUE *argv, VALUE self)
308
+ {
309
+ xmlXPathContextPtr xctxt;
310
+ VALUE size;
311
+ int value = -1;
312
+
313
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
314
+
315
+ if (rb_scan_args(argc, argv, "01", &size) == 1)
316
+ {
317
+ value = NUM2INT(size);
318
+ }
319
+
320
+ if (xmlXPathContextSetCache(xctxt, 1, value, 0) == -1)
321
+ rxml_raise(&xmlLastError);
322
+
323
+ return self;
324
+ }
325
+
326
+ /*
327
+ * call-seq:
328
+ * context.disable_cache
329
+ *
330
+ * Disables an XPath::Context's built-in cache.
331
+ */
332
+ static VALUE
333
+ rxml_xpath_context_disable_cache(VALUE self)
334
+ {
335
+ xmlXPathContextPtr xctxt;
336
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
337
+
338
+ if (xmlXPathContextSetCache(xctxt, 0, 0, 0) == -1)
339
+ rxml_raise(&xmlLastError);
340
+
341
+ return self;
342
+ }
343
+ #endif
344
+
345
+ void rxml_init_xpath_context(void)
346
+ {
347
+ cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
348
+ rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
349
+ rb_define_method(cXMLXPathContext, "doc", rxml_xpath_context_doc, 0);
350
+ rb_define_method(cXMLXPathContext, "initialize", rxml_xpath_context_initialize, 1);
351
+ rb_define_method(cXMLXPathContext, "register_namespaces", rxml_xpath_context_register_namespaces, 1);
352
+ rb_define_method(cXMLXPathContext, "register_namespaces_from_node", rxml_xpath_context_register_namespaces_from_node, 1);
353
+ rb_define_method(cXMLXPathContext, "register_namespace", rxml_xpath_context_register_namespace, 2);
354
+ rb_define_method(cXMLXPathContext, "node=", rxml_xpath_context_node_set, 1);
355
+ rb_define_method(cXMLXPathContext, "find", rxml_xpath_context_find, 1);
356
+ #if LIBXML_VERSION >= 20626
357
+ rb_define_method(cXMLXPathContext, "enable_cache", rxml_xpath_context_enable_cache, -1);
358
+ rb_define_method(cXMLXPathContext, "disable_cache", rxml_xpath_context_disable_cache, 0);
359
+ #endif
360
+ }