libxml-ruby 3.2.2-x64-mingw-ucrt

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 +7 -0
  2. data/HISTORY +848 -0
  3. data/LICENSE +21 -0
  4. data/MANIFEST +166 -0
  5. data/README.rdoc +217 -0
  6. data/Rakefile +99 -0
  7. data/ext/libxml/extconf.rb +61 -0
  8. data/ext/libxml/libxml.c +80 -0
  9. data/ext/libxml/libxml_ruby.def +35 -0
  10. data/ext/libxml/ruby_libxml.h +67 -0
  11. data/ext/libxml/ruby_xml.c +933 -0
  12. data/ext/libxml/ruby_xml.h +10 -0
  13. data/ext/libxml/ruby_xml_attr.c +333 -0
  14. data/ext/libxml/ruby_xml_attr.h +12 -0
  15. data/ext/libxml/ruby_xml_attr_decl.c +153 -0
  16. data/ext/libxml/ruby_xml_attr_decl.h +11 -0
  17. data/ext/libxml/ruby_xml_attributes.c +275 -0
  18. data/ext/libxml/ruby_xml_attributes.h +15 -0
  19. data/ext/libxml/ruby_xml_cbg.c +85 -0
  20. data/ext/libxml/ruby_xml_document.c +1123 -0
  21. data/ext/libxml/ruby_xml_document.h +11 -0
  22. data/ext/libxml/ruby_xml_dtd.c +248 -0
  23. data/ext/libxml/ruby_xml_dtd.h +9 -0
  24. data/ext/libxml/ruby_xml_encoding.c +250 -0
  25. data/ext/libxml/ruby_xml_encoding.h +16 -0
  26. data/ext/libxml/ruby_xml_error.c +996 -0
  27. data/ext/libxml/ruby_xml_error.h +12 -0
  28. data/ext/libxml/ruby_xml_html_parser.c +89 -0
  29. data/ext/libxml/ruby_xml_html_parser.h +10 -0
  30. data/ext/libxml/ruby_xml_html_parser_context.c +337 -0
  31. data/ext/libxml/ruby_xml_html_parser_context.h +10 -0
  32. data/ext/libxml/ruby_xml_html_parser_options.c +46 -0
  33. data/ext/libxml/ruby_xml_html_parser_options.h +10 -0
  34. data/ext/libxml/ruby_xml_input_cbg.c +191 -0
  35. data/ext/libxml/ruby_xml_input_cbg.h +20 -0
  36. data/ext/libxml/ruby_xml_io.c +47 -0
  37. data/ext/libxml/ruby_xml_io.h +10 -0
  38. data/ext/libxml/ruby_xml_namespace.c +153 -0
  39. data/ext/libxml/ruby_xml_namespace.h +10 -0
  40. data/ext/libxml/ruby_xml_namespaces.c +293 -0
  41. data/ext/libxml/ruby_xml_namespaces.h +9 -0
  42. data/ext/libxml/ruby_xml_node.c +1402 -0
  43. data/ext/libxml/ruby_xml_node.h +13 -0
  44. data/ext/libxml/ruby_xml_parser.c +91 -0
  45. data/ext/libxml/ruby_xml_parser.h +12 -0
  46. data/ext/libxml/ruby_xml_parser_context.c +999 -0
  47. data/ext/libxml/ruby_xml_parser_context.h +10 -0
  48. data/ext/libxml/ruby_xml_parser_options.c +66 -0
  49. data/ext/libxml/ruby_xml_parser_options.h +12 -0
  50. data/ext/libxml/ruby_xml_reader.c +1239 -0
  51. data/ext/libxml/ruby_xml_reader.h +17 -0
  52. data/ext/libxml/ruby_xml_relaxng.c +110 -0
  53. data/ext/libxml/ruby_xml_relaxng.h +10 -0
  54. data/ext/libxml/ruby_xml_sax2_handler.c +326 -0
  55. data/ext/libxml/ruby_xml_sax2_handler.h +10 -0
  56. data/ext/libxml/ruby_xml_sax_parser.c +116 -0
  57. data/ext/libxml/ruby_xml_sax_parser.h +10 -0
  58. data/ext/libxml/ruby_xml_schema.c +278 -0
  59. data/ext/libxml/ruby_xml_schema.h +809 -0
  60. data/ext/libxml/ruby_xml_schema_attribute.c +109 -0
  61. data/ext/libxml/ruby_xml_schema_attribute.h +15 -0
  62. data/ext/libxml/ruby_xml_schema_element.c +95 -0
  63. data/ext/libxml/ruby_xml_schema_element.h +14 -0
  64. data/ext/libxml/ruby_xml_schema_facet.c +52 -0
  65. data/ext/libxml/ruby_xml_schema_facet.h +13 -0
  66. data/ext/libxml/ruby_xml_schema_type.c +232 -0
  67. data/ext/libxml/ruby_xml_schema_type.h +9 -0
  68. data/ext/libxml/ruby_xml_version.h +9 -0
  69. data/ext/libxml/ruby_xml_writer.c +1133 -0
  70. data/ext/libxml/ruby_xml_writer.h +10 -0
  71. data/ext/libxml/ruby_xml_xinclude.c +16 -0
  72. data/ext/libxml/ruby_xml_xinclude.h +11 -0
  73. data/ext/libxml/ruby_xml_xpath.c +194 -0
  74. data/ext/libxml/ruby_xml_xpath.h +13 -0
  75. data/ext/libxml/ruby_xml_xpath_context.c +360 -0
  76. data/ext/libxml/ruby_xml_xpath_context.h +9 -0
  77. data/ext/libxml/ruby_xml_xpath_expression.c +81 -0
  78. data/ext/libxml/ruby_xml_xpath_expression.h +10 -0
  79. data/ext/libxml/ruby_xml_xpath_object.c +338 -0
  80. data/ext/libxml/ruby_xml_xpath_object.h +17 -0
  81. data/ext/libxml/ruby_xml_xpointer.c +99 -0
  82. data/ext/libxml/ruby_xml_xpointer.h +11 -0
  83. data/ext/vc/libxml_ruby.sln +28 -0
  84. data/lib/3.1/libxml_ruby.so +0 -0
  85. data/lib/libxml/attr.rb +123 -0
  86. data/lib/libxml/attr_decl.rb +80 -0
  87. data/lib/libxml/attributes.rb +14 -0
  88. data/lib/libxml/document.rb +194 -0
  89. data/lib/libxml/error.rb +95 -0
  90. data/lib/libxml/hpricot.rb +78 -0
  91. data/lib/libxml/html_parser.rb +96 -0
  92. data/lib/libxml/namespace.rb +62 -0
  93. data/lib/libxml/namespaces.rb +38 -0
  94. data/lib/libxml/node.rb +323 -0
  95. data/lib/libxml/parser.rb +101 -0
  96. data/lib/libxml/sax_callbacks.rb +180 -0
  97. data/lib/libxml/sax_parser.rb +41 -0
  98. data/lib/libxml/schema/attribute.rb +19 -0
  99. data/lib/libxml/schema/element.rb +19 -0
  100. data/lib/libxml/schema/type.rb +21 -0
  101. data/lib/libxml/schema.rb +48 -0
  102. data/lib/libxml/tree.rb +29 -0
  103. data/lib/libxml-ruby.rb +30 -0
  104. data/lib/libxml.rb +5 -0
  105. data/lib/xml/libxml.rb +10 -0
  106. data/lib/xml.rb +14 -0
  107. data/libxml-ruby.gemspec +48 -0
  108. data/script/benchmark/depixelate +634 -0
  109. data/script/benchmark/hamlet.xml +9055 -0
  110. data/script/benchmark/parsecount +170 -0
  111. data/script/benchmark/sock_entries.xml +507 -0
  112. data/script/benchmark/throughput +41 -0
  113. data/script/test +6 -0
  114. data/setup.rb +1584 -0
  115. data/test/c14n/given/doc.dtd +1 -0
  116. data/test/c14n/given/example-1.xml +14 -0
  117. data/test/c14n/given/example-2.xml +11 -0
  118. data/test/c14n/given/example-3.xml +18 -0
  119. data/test/c14n/given/example-4.xml +9 -0
  120. data/test/c14n/given/example-5.xml +12 -0
  121. data/test/c14n/given/example-6.xml +2 -0
  122. data/test/c14n/given/example-7.xml +11 -0
  123. data/test/c14n/given/example-8.xml +11 -0
  124. data/test/c14n/given/example-8.xpath +10 -0
  125. data/test/c14n/given/world.txt +1 -0
  126. data/test/c14n/result/1-1-without-comments/example-1 +4 -0
  127. data/test/c14n/result/1-1-without-comments/example-2 +11 -0
  128. data/test/c14n/result/1-1-without-comments/example-3 +14 -0
  129. data/test/c14n/result/1-1-without-comments/example-4 +9 -0
  130. data/test/c14n/result/1-1-without-comments/example-5 +3 -0
  131. data/test/c14n/result/1-1-without-comments/example-6 +1 -0
  132. data/test/c14n/result/1-1-without-comments/example-7 +1 -0
  133. data/test/c14n/result/1-1-without-comments/example-8 +1 -0
  134. data/test/c14n/result/with-comments/example-1 +6 -0
  135. data/test/c14n/result/with-comments/example-2 +11 -0
  136. data/test/c14n/result/with-comments/example-3 +14 -0
  137. data/test/c14n/result/with-comments/example-4 +9 -0
  138. data/test/c14n/result/with-comments/example-5 +4 -0
  139. data/test/c14n/result/with-comments/example-6 +1 -0
  140. data/test/c14n/result/with-comments/example-7 +1 -0
  141. data/test/c14n/result/without-comments/example-1 +4 -0
  142. data/test/c14n/result/without-comments/example-2 +11 -0
  143. data/test/c14n/result/without-comments/example-3 +14 -0
  144. data/test/c14n/result/without-comments/example-4 +9 -0
  145. data/test/c14n/result/without-comments/example-5 +3 -0
  146. data/test/c14n/result/without-comments/example-6 +1 -0
  147. data/test/c14n/result/without-comments/example-7 +1 -0
  148. data/test/model/atom.xml +13 -0
  149. data/test/model/bands.iso-8859-1.xml +5 -0
  150. data/test/model/bands.utf-8.xml +5 -0
  151. data/test/model/bands.xml +5 -0
  152. data/test/model/books.xml +154 -0
  153. data/test/model/cwm_1_0.xml +11336 -0
  154. data/test/model/merge_bug_data.xml +58 -0
  155. data/test/model/ruby-lang.html +238 -0
  156. data/test/model/rubynet.xml +79 -0
  157. data/test/model/rubynet_project +1 -0
  158. data/test/model/shiporder.rnc +28 -0
  159. data/test/model/shiporder.rng +86 -0
  160. data/test/model/shiporder.xml +23 -0
  161. data/test/model/shiporder.xsd +40 -0
  162. data/test/model/soap.xml +27 -0
  163. data/test/model/xinclude.xml +5 -0
  164. data/test/test_attr.rb +181 -0
  165. data/test/test_attr_decl.rb +132 -0
  166. data/test/test_attributes.rb +136 -0
  167. data/test/test_canonicalize.rb +120 -0
  168. data/test/test_deprecated_require.rb +12 -0
  169. data/test/test_document.rb +132 -0
  170. data/test/test_document_write.rb +146 -0
  171. data/test/test_dtd.rb +129 -0
  172. data/test/test_encoding.rb +129 -0
  173. data/test/test_encoding_sax.rb +115 -0
  174. data/test/test_error.rb +178 -0
  175. data/test/test_helper.rb +9 -0
  176. data/test/test_html_parser.rb +162 -0
  177. data/test/test_html_parser_context.rb +23 -0
  178. data/test/test_namespace.rb +60 -0
  179. data/test/test_namespaces.rb +200 -0
  180. data/test/test_node.rb +237 -0
  181. data/test/test_node_cdata.rb +50 -0
  182. data/test/test_node_comment.rb +32 -0
  183. data/test/test_node_copy.rb +40 -0
  184. data/test/test_node_edit.rb +158 -0
  185. data/test/test_node_pi.rb +37 -0
  186. data/test/test_node_text.rb +69 -0
  187. data/test/test_node_write.rb +97 -0
  188. data/test/test_node_xlink.rb +28 -0
  189. data/test/test_parser.rb +324 -0
  190. data/test/test_parser_context.rb +198 -0
  191. data/test/test_properties.rb +38 -0
  192. data/test/test_reader.rb +364 -0
  193. data/test/test_relaxng.rb +53 -0
  194. data/test/test_sax_parser.rb +326 -0
  195. data/test/test_schema.rb +168 -0
  196. data/test/test_suite.rb +48 -0
  197. data/test/test_traversal.rb +152 -0
  198. data/test/test_writer.rb +468 -0
  199. data/test/test_xinclude.rb +20 -0
  200. data/test/test_xml.rb +263 -0
  201. data/test/test_xpath.rb +244 -0
  202. data/test/test_xpath_context.rb +88 -0
  203. data/test/test_xpath_expression.rb +37 -0
  204. data/test/test_xpointer.rb +72 -0
  205. metadata +325 -0
@@ -0,0 +1,10 @@
1
+ #ifndef __RXML_WRITER__
2
+ #define __RXML_WRITER__
3
+
4
+ #ifdef LIBXML_WRITER_ENABLED
5
+ #include <libxml/xmlwriter.h>
6
+ #endif
7
+
8
+ extern VALUE cXMLWriter;
9
+ void rxml_init_writer(void);
10
+ #endif
@@ -0,0 +1,16 @@
1
+ #include "ruby_libxml.h"
2
+ #include "ruby_xml_xinclude.h"
3
+
4
+ VALUE cXMLXInclude;
5
+
6
+ /*
7
+ * Document-class: LibXML::XML::XInclude
8
+ *
9
+ * The ruby bindings do not currently expose libxml's
10
+ * XInclude fuctionality.
11
+ */
12
+
13
+ void rxml_init_xinclude(void)
14
+ {
15
+ cXMLXInclude = rb_define_class_under(mXML, "XInclude", rb_cObject);
16
+ }
@@ -0,0 +1,11 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_XINCLUDE__
4
+ #define __RXML_XINCLUDE__
5
+
6
+ extern VALUE cXMLXInclude;
7
+ extern VALUE eXMLXIncludeError;
8
+
9
+ void rxml_init_xinclude(void);
10
+
11
+ #endif
@@ -0,0 +1,194 @@
1
+ /*
2
+ * Document-class: LibXML::XML::XPath
3
+ *
4
+ * The XML::XPath module is used to query XML documents. It is
5
+ * usually accessed via the XML::Document#find or
6
+ * XML::Node#find methods. For example:
7
+ *
8
+ * document.find('/foo', namespaces) -> XML::XPath::Object
9
+ *
10
+ * The optional namespaces parameter can be a string, array or
11
+ * hash table.
12
+ *
13
+ * document.find('/foo', 'xlink:http://www.w3.org/1999/xlink')
14
+ * document.find('/foo', ['xlink:http://www.w3.org/1999/xlink',
15
+ * 'xi:http://www.w3.org/2001/XInclude')
16
+ * document.find('/foo', 'xlink' => 'http://www.w3.org/1999/xlink',
17
+ * 'xi' => 'http://www.w3.org/2001/XInclude')
18
+ *
19
+ *
20
+ * === Working With Default Namespaces
21
+ *
22
+ * Finding namespaced elements and attributes can be tricky.
23
+ * Lets work through an example of a document with a default
24
+ * namespace:
25
+ *
26
+ * <?xml version="1.0" encoding="utf-8"?>
27
+ * <feed xmlns="http://www.w3.org/2005/Atom">
28
+ * <title type="text">Phil Bogle's Contacts</title>
29
+ * </feed>
30
+ *
31
+ * To find nodes you must define the atom namespace for
32
+ * libxml. One way to do this is:
33
+ *
34
+ * node = doc.find('atom:title', 'atom:http://www.w3.org/2005/Atom')
35
+ *
36
+ * Alternatively, you can register the default namespace like this:
37
+ *
38
+ * doc.root.namespaces.default_prefix = 'atom'
39
+ * node = doc.find('atom:title')
40
+ *
41
+ * === More Complex Namespace Examples
42
+ *
43
+ * Lets work through some more complex examples using the
44
+ * following xml document:
45
+ *
46
+ * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
47
+ * <soap:Body>
48
+ * <getManufacturerNamesResponse xmlns="http://services.somewhere.com">
49
+ * <IDAndNameList xmlns="http://services.somewhere.com">
50
+ * <ns1:IdAndName xmlns:ns1="http://domain.somewhere.com"/>
51
+ * </IDAndNameList>
52
+ * </getManufacturerNamesResponse>
53
+ * </soap:Body>
54
+ * </soap:Envelope>
55
+ *
56
+ * # Since the soap namespace is defined on the root
57
+ * # node we can directly use it.
58
+ * doc.find('/soap:Envelope')
59
+ *
60
+ * # Since the ns1 namespace is not defined on the root node
61
+ * # we have to first register it with the xpath engine.
62
+ * doc.find('//ns1:IdAndName',
63
+ * 'ns1:http://domain.somewhere.com')
64
+ *
65
+ * # Since the getManufacturerNamesResponse element uses a default
66
+ * # namespace we first have to give it a prefix and register
67
+ * # it with the xpath engine.
68
+ * doc.find('//ns:getManufacturerNamesResponse',
69
+ * 'ns:http://services.somewhere.com')
70
+ *
71
+ * # Here is an example showing a complex namespace aware
72
+ * # xpath expression.
73
+ * doc.find('/soap:Envelope/soap:Body/ns0:getManufacturerNamesResponse/ns0:IDAndNameList/ns1:IdAndName',
74
+ * ['ns0:http://services.somewhere.com', 'ns1:http://domain.somewhere.com'])
75
+ */
76
+
77
+ #include "ruby_libxml.h"
78
+
79
+ VALUE mXPath;
80
+
81
+ VALUE rxml_xpath_to_value(xmlXPathContextPtr xctxt, xmlXPathObjectPtr xobject)
82
+ {
83
+ VALUE result;
84
+ int type;
85
+
86
+ if (xobject == NULL)
87
+ {
88
+ /* xmlLastError is different than xctxt->lastError. Use
89
+ xmlLastError since it has the message set while xctxt->lastError
90
+ does not. */
91
+ xmlErrorPtr xerror = xmlGetLastError();
92
+ rxml_raise(xerror);
93
+ }
94
+
95
+ switch (type = xobject->type)
96
+ {
97
+ case XPATH_NODESET:
98
+ result = rxml_xpath_object_wrap(xctxt->doc, xobject);
99
+ break;
100
+ case XPATH_BOOLEAN:
101
+ result = (xobject->boolval != 0) ? Qtrue : Qfalse;
102
+ xmlXPathFreeObject(xobject);
103
+ break;
104
+ case XPATH_NUMBER:
105
+ result = rb_float_new(xobject->floatval);
106
+ xmlXPathFreeObject(xobject);
107
+ break;
108
+ case XPATH_STRING:
109
+ result = rxml_new_cstr(xobject->stringval, xctxt->doc->encoding);
110
+ xmlXPathFreeObject(xobject);
111
+ break;
112
+ default:
113
+ xmlXPathFreeObject(xobject);
114
+ rb_raise(rb_eTypeError,
115
+ "can't convert XPath object of type %d to Ruby value", type
116
+ );
117
+ }
118
+
119
+ return result;
120
+ }
121
+
122
+ xmlXPathObjectPtr rxml_xpath_from_value(VALUE value)
123
+ {
124
+ xmlXPathObjectPtr result = NULL;
125
+
126
+ switch (TYPE(value))
127
+ {
128
+ case T_TRUE:
129
+ case T_FALSE:
130
+ result = xmlXPathNewBoolean(RTEST(value));
131
+ break;
132
+ case T_FIXNUM:
133
+ case T_FLOAT:
134
+ result = xmlXPathNewFloat(NUM2DBL(value));
135
+ break;
136
+ case T_STRING:
137
+ result = xmlXPathWrapString(xmlStrdup((const xmlChar *)StringValuePtr(value)));
138
+ break;
139
+ case T_NIL:
140
+ result = xmlXPathNewNodeSet(NULL);
141
+ break;
142
+ case T_ARRAY:
143
+ {
144
+ long i, j;
145
+ result = xmlXPathNewNodeSet(NULL);
146
+
147
+ for (i = RARRAY_LEN(value); i > 0; i--)
148
+ {
149
+ xmlXPathObjectPtr obj = rxml_xpath_from_value(rb_ary_shift(value));
150
+
151
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0))
152
+ {
153
+ for (j = 0; j < obj->nodesetval->nodeNr; j++)
154
+ {
155
+ xmlXPathNodeSetAdd(result->nodesetval, obj->nodesetval->nodeTab[j]);
156
+ }
157
+ }
158
+ }
159
+ break;
160
+ }
161
+ default:
162
+ rb_raise(rb_eTypeError,
163
+ "can't convert object of type %s to XPath object", rb_obj_classname(value)
164
+ );
165
+ }
166
+
167
+ return result;
168
+ }
169
+
170
+ void rxml_init_xpath(void)
171
+ {
172
+ mXPath = rb_define_module_under(mXML, "XPath");
173
+
174
+ /* 0: Undefined value. */
175
+ rb_define_const(mXPath, "UNDEFINED", INT2NUM(XPATH_UNDEFINED));
176
+ /* 1: A nodeset, will be wrapped by XPath Object. */
177
+ rb_define_const(mXPath, "NODESET", INT2NUM(XPATH_NODESET));
178
+ /* 2: A boolean value. */
179
+ rb_define_const(mXPath, "BOOLEAN", INT2NUM(XPATH_BOOLEAN));
180
+ /* 3: A numeric value. */
181
+ rb_define_const(mXPath, "NUMBER", INT2NUM(XPATH_NUMBER));
182
+ /* 4: A string value. */
183
+ rb_define_const(mXPath, "STRING", INT2NUM(XPATH_STRING));
184
+ /* 5: An xpointer point */
185
+ rb_define_const(mXPath, "POINT", INT2NUM(XPATH_POINT));
186
+ /* 6: An xpointer range */
187
+ rb_define_const(mXPath, "RANGE", INT2NUM(XPATH_RANGE));
188
+ /* 7: An xpointer location set */
189
+ rb_define_const(mXPath, "LOCATIONSET", INT2NUM(XPATH_LOCATIONSET));
190
+ /* 8: XPath user type */
191
+ rb_define_const(mXPath, "USERS", INT2NUM(XPATH_USERS));
192
+ /* 9: An XSLT value tree, non modifiable */
193
+ rb_define_const(mXPath, "XSLT_TREE", INT2NUM(XPATH_XSLT_TREE));
194
+ }
@@ -0,0 +1,13 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_XPATH__
4
+ #define __RXML_XPATH__
5
+
6
+ extern VALUE mXPath;
7
+
8
+ void rxml_init_xpath(void);
9
+
10
+ VALUE rxml_xpath_to_value(xmlXPathContextPtr, xmlXPathObjectPtr);
11
+ xmlXPathObjectPtr rxml_xpath_from_value(VALUE);
12
+
13
+ #endif
@@ -0,0 +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
+ 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
+ }
@@ -0,0 +1,9 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_XPATH_CONTEXT__
4
+ #define __RXML_XPATH_CONTEXT__
5
+
6
+ extern VALUE cXMLXPathContext;
7
+ void rxml_init_xpath_context(void);
8
+
9
+ #endif
@@ -0,0 +1,81 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #include "ruby_libxml.h"
4
+ #include "ruby_xml_xpath.h"
5
+ #include "ruby_xml_xpath_expression.h"
6
+
7
+ /*
8
+ * Document-class: LibXML::XML::XPath::Expression
9
+ *
10
+ * The XML::XPath::Expression class is used to compile
11
+ * XPath expressions so they can be parsed only once
12
+ * but reused multiple times.
13
+ *
14
+ * doc = XML::Document.string(IO.read('some xml file'))
15
+ * expr = XPath::Expression.new('//first')
16
+ * doc.root.each do |node|
17
+ * result = node.find(expr) # many, many, many times
18
+ * # ...
19
+ * end
20
+ */
21
+
22
+ VALUE cXMLXPathExpression;
23
+
24
+ static void rxml_xpath_expression_free(xmlXPathCompExprPtr expr)
25
+ {
26
+ xmlXPathFreeCompExpr(expr);
27
+ }
28
+
29
+ static VALUE rxml_xpath_expression_alloc(VALUE klass)
30
+ {
31
+ return Data_Wrap_Struct(cXMLXPathExpression, NULL,
32
+ rxml_xpath_expression_free, NULL);
33
+ }
34
+
35
+ /* call-seq:
36
+ * XPath::Expression.compile(expression) -> XPath::Expression
37
+ *
38
+ * Compiles an XPatch expression. This improves performance
39
+ * when an XPath expression is called multiple times.
40
+ *
41
+ * doc = XML::Document.string('<header><first>hi</first></header>')
42
+ * expr = XPath::Expression.new('//first')
43
+ * nodes = doc.find(expr)
44
+ */
45
+ static VALUE rxml_xpath_expression_compile(VALUE klass, VALUE expression)
46
+ {
47
+ VALUE args[] = {expression};
48
+ return rb_class_new_instance(1, args, cXMLXPathExpression);
49
+ }
50
+
51
+ /* call-seq:
52
+ * XPath::Expression.new(expression) -> XPath::Expression
53
+ *
54
+ * Compiles an XPatch expression. This improves performance
55
+ * when an XPath expression is called multiple times.
56
+ *
57
+ * doc = XML::Document.string('<header><first>hi</first></header>')
58
+ * expr = XPath::Expression.new('//first')
59
+ * nodes = doc.find(expr)
60
+ */
61
+ static VALUE rxml_xpath_expression_initialize(VALUE self, VALUE expression)
62
+ {
63
+ xmlXPathCompExprPtr compexpr = xmlXPathCompile((const xmlChar*)StringValueCStr(expression));
64
+
65
+ if (compexpr == NULL)
66
+ {
67
+ xmlErrorPtr xerror = xmlGetLastError();
68
+ rxml_raise(xerror);
69
+ }
70
+
71
+ DATA_PTR( self) = compexpr;
72
+ return self;
73
+ }
74
+
75
+ void rxml_init_xpath_expression(void)
76
+ {
77
+ cXMLXPathExpression = rb_define_class_under(mXPath, "Expression", rb_cObject);
78
+ rb_define_alloc_func(cXMLXPathExpression, rxml_xpath_expression_alloc);
79
+ rb_define_singleton_method(cXMLXPathExpression, "compile", rxml_xpath_expression_compile, 1);
80
+ rb_define_method(cXMLXPathExpression, "initialize", rxml_xpath_expression_initialize, 1);
81
+ }