libxml-ruby 0.9.1-x86-mswin32-60 → 0.9.2-x86-mswin32-60
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.
- data/CHANGES +6 -0
- data/ext/libxml/libxml.c +2 -1
- data/ext/libxml/libxml.c.rej +16 -0
- data/ext/libxml/ruby_libxml.h +72 -71
- data/ext/libxml/ruby_xml_error.c +11 -0
- data/ext/libxml/ruby_xml_html_parser.c +133 -133
- data/ext/libxml/ruby_xml_parser.c +3 -3
- data/ext/libxml/ruby_xml_sax_parser.c +228 -228
- data/ext/libxml/ruby_xml_xpath_context.c +294 -281
- data/ext/libxml/ruby_xml_xpath_expression.c +69 -0
- data/ext/libxml/ruby_xml_xpath_expression.h +12 -0
- data/ext/libxml/version.h +2 -2
- data/ext/mingw/libxml_ruby.dll.a +0 -0
- data/ext/mingw/libxml_ruby.so +0 -0
- data/ext/vc/libxml_ruby.vcproj +9 -1
- data/test/tc_document_write.rb +14 -0
- data/test/tc_xpath_expression.rb +35 -0
- data/test/test_suite.rb +1 -0
- metadata +7 -2
@@ -1,281 +1,294 @@
|
|
1
|
-
/* $Id: ruby_xml_xpath_context.c
|
2
|
-
|
3
|
-
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
-
|
5
|
-
#include "ruby_libxml.h"
|
6
|
-
#include "ruby_xml_xpath_context.h"
|
7
|
-
#include
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
*
|
13
|
-
*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
* context
|
20
|
-
* context.
|
21
|
-
*
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
*
|
43
|
-
*
|
44
|
-
*
|
45
|
-
*
|
46
|
-
*
|
47
|
-
*
|
48
|
-
*
|
49
|
-
* nodes.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
*
|
87
|
-
*
|
88
|
-
*
|
89
|
-
*
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
(xmlChar*)StringValuePtr(
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
}
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
*
|
113
|
-
*
|
114
|
-
*
|
115
|
-
*
|
116
|
-
*
|
117
|
-
* context.
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
VALUE
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
*
|
176
|
-
*
|
177
|
-
*
|
178
|
-
*
|
179
|
-
*
|
180
|
-
* context.register_namespaces(
|
181
|
-
*
|
182
|
-
*
|
183
|
-
*
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
*
|
223
|
-
*
|
224
|
-
*
|
225
|
-
|
226
|
-
|
227
|
-
*
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
Data_Get_Struct(
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
*
|
243
|
-
*
|
244
|
-
*
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
{
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
1
|
+
/* $Id: ruby_xml_xpath_context.c 600 2008-11-19 07:39:29Z cfis $ */
|
2
|
+
|
3
|
+
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
+
|
5
|
+
#include "ruby_libxml.h"
|
6
|
+
#include "ruby_xml_xpath_context.h"
|
7
|
+
#include "ruby_xml_xpath_expression.h"
|
8
|
+
#include <st.h>
|
9
|
+
|
10
|
+
|
11
|
+
/*
|
12
|
+
* Document-class: LibXML::XML::XPath::Context
|
13
|
+
*
|
14
|
+
* The XML::XPath::Context class is used to evaluate XPath
|
15
|
+
* expressions. Generally, you should not directly use this class,
|
16
|
+
* but instead use the XML::Document#find and XML::Node#find methods.
|
17
|
+
*
|
18
|
+
* doc = XML::Document.string('<header>content</header>')
|
19
|
+
* context = XPath::Context.new(doc)
|
20
|
+
* context.node = doc.root
|
21
|
+
* context.register_namespaces_from_node(doc.root)
|
22
|
+
* nodes = context.find('/header')
|
23
|
+
*/
|
24
|
+
|
25
|
+
VALUE cXMLXPathContext;
|
26
|
+
|
27
|
+
void
|
28
|
+
ruby_xml_xpath_context_free(xmlXPathContextPtr ctxt) {
|
29
|
+
xmlXPathFreeContext(ctxt);
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
VALUE
|
34
|
+
ruby_xml_xpath_context_alloc(VALUE klass) {
|
35
|
+
return Data_Wrap_Struct(cXMLXPathContext,
|
36
|
+
NULL,
|
37
|
+
ruby_xml_xpath_context_free,
|
38
|
+
NULL);
|
39
|
+
}
|
40
|
+
|
41
|
+
/* call-seq:
|
42
|
+
* XPath::Context.new(node) -> XPath::Context
|
43
|
+
*
|
44
|
+
* Creates a new XPath context for the specified document. The
|
45
|
+
* context can then be used to evaluate an XPath expression.
|
46
|
+
*
|
47
|
+
* doc = XML::Document.string('<header><first>hi</first></header>')
|
48
|
+
* context = XPath::Context.new(doc)
|
49
|
+
* nodes = XPath::Object.new('//first', context)
|
50
|
+
* nodes.length == 1
|
51
|
+
*/
|
52
|
+
VALUE
|
53
|
+
ruby_xml_xpath_context_initialize(VALUE self, VALUE node) {
|
54
|
+
xmlDocPtr xdoc;
|
55
|
+
VALUE document;
|
56
|
+
#ifndef LIBXML_XPATH_ENABLED
|
57
|
+
rb_raise(rb_eTypeError, "libxml was not compiled with XPath support.");
|
58
|
+
#endif
|
59
|
+
|
60
|
+
if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
|
61
|
+
{
|
62
|
+
document = rb_funcall(node, rb_intern("doc"), 0);
|
63
|
+
if NIL_P(document)
|
64
|
+
rb_raise(rb_eTypeError, "Supplied node must belong to a document.");
|
65
|
+
}
|
66
|
+
else if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
|
67
|
+
{
|
68
|
+
document = node;
|
69
|
+
}
|
70
|
+
else
|
71
|
+
{
|
72
|
+
rb_raise(rb_eTypeError, "Supplied argument must be a document or node.");
|
73
|
+
}
|
74
|
+
|
75
|
+
Data_Get_Struct(document, xmlDoc, xdoc);
|
76
|
+
DATA_PTR(self) = xmlXPathNewContext(xdoc);
|
77
|
+
|
78
|
+
/* Save the doc as an attribute, this will expose it to Ruby's GC. */
|
79
|
+
rb_iv_set(self, "@doc", document);
|
80
|
+
|
81
|
+
return self;
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
/*
|
86
|
+
* call-seq:
|
87
|
+
* context.register_namespace(prefix, uri) -> (true|false)
|
88
|
+
*
|
89
|
+
* Register the specified namespace URI with the specified prefix
|
90
|
+
* in this context.
|
91
|
+
|
92
|
+
* context.register_namespace('xi', 'http://www.w3.org/2001/XInclude')
|
93
|
+
*/
|
94
|
+
VALUE
|
95
|
+
ruby_xml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri) {
|
96
|
+
xmlXPathContextPtr ctxt;
|
97
|
+
|
98
|
+
Data_Get_Struct(self, xmlXPathContext, ctxt);
|
99
|
+
if (xmlXPathRegisterNs(ctxt,
|
100
|
+
(xmlChar*)StringValuePtr(prefix),
|
101
|
+
(xmlChar*)StringValuePtr(uri))
|
102
|
+
== 0) {
|
103
|
+
return(Qtrue);
|
104
|
+
} else {
|
105
|
+
/* Should raise an exception, IMHO (whose?, why shouldnt it? -danj)*/
|
106
|
+
rb_warning("register namespace failed");
|
107
|
+
return(Qfalse);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
/* call-seq:
|
112
|
+
* context.register_namespaces_from_node(node) -> self
|
113
|
+
*
|
114
|
+
* Helper method to read in namespaces defined on a node.
|
115
|
+
*
|
116
|
+
* doc = XML::Document.string('<header><first>hi</first></header>')
|
117
|
+
* context = XPath::Context.new(doc)
|
118
|
+
* context.register_namespaces_from_node(doc.root)
|
119
|
+
*/
|
120
|
+
VALUE
|
121
|
+
ruby_xml_xpath_context_register_namespaces_from_node(VALUE self, VALUE node) {
|
122
|
+
xmlXPathContextPtr xctxt;
|
123
|
+
xmlNodePtr xnode;
|
124
|
+
xmlNsPtr *xnsArr;
|
125
|
+
|
126
|
+
Data_Get_Struct(self, xmlXPathContext, xctxt);
|
127
|
+
|
128
|
+
if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
|
129
|
+
{
|
130
|
+
xmlDocPtr xdoc;
|
131
|
+
Data_Get_Struct(node, xmlDoc, xdoc);
|
132
|
+
xnode = xmlDocGetRootElement(xdoc);
|
133
|
+
}
|
134
|
+
else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
|
135
|
+
{
|
136
|
+
Data_Get_Struct(node, xmlNode, xnode);
|
137
|
+
}
|
138
|
+
else
|
139
|
+
{
|
140
|
+
rb_raise(rb_eTypeError, "The first argument must be a document or node.");
|
141
|
+
}
|
142
|
+
|
143
|
+
xnsArr = xmlGetNsList(xnode->doc, xnode);
|
144
|
+
|
145
|
+
if (xnsArr)
|
146
|
+
{
|
147
|
+
xmlNsPtr xns = *xnsArr;
|
148
|
+
|
149
|
+
while (xns) {
|
150
|
+
/* If there is no prefix, then this is the default namespace.
|
151
|
+
Skip it for now. */
|
152
|
+
if (xns->prefix)
|
153
|
+
{
|
154
|
+
VALUE prefix = rb_str_new2(xns->prefix);
|
155
|
+
VALUE uri = rb_str_new2(xns->href);
|
156
|
+
ruby_xml_xpath_context_register_namespace(self, prefix, uri);
|
157
|
+
}
|
158
|
+
xns = xns->next;
|
159
|
+
}
|
160
|
+
xmlFree(xnsArr);
|
161
|
+
}
|
162
|
+
|
163
|
+
return self;
|
164
|
+
}
|
165
|
+
|
166
|
+
static int
|
167
|
+
iterate_ns_hash(st_data_t prefix, st_data_t uri, st_data_t self)
|
168
|
+
{
|
169
|
+
ruby_xml_xpath_context_register_namespace(self, prefix, uri);
|
170
|
+
return ST_CONTINUE;
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
/*
|
175
|
+
* call-seq:
|
176
|
+
* context.register_namespaces(["prefix:uri"]) -> self
|
177
|
+
*
|
178
|
+
* Register the specified namespaces in this context.
|
179
|
+
*
|
180
|
+
* context.register_namespaces('xi:http://www.w3.org/2001/XInclude')
|
181
|
+
* context.register_namespaces(['xlink:http://www.w3.org/1999/xlink',
|
182
|
+
* 'xi:http://www.w3.org/2001/XInclude')
|
183
|
+
* context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink',
|
184
|
+
* 'xi' => 'http://www.w3.org/2001/XInclude')
|
185
|
+
*/
|
186
|
+
VALUE
|
187
|
+
ruby_xml_xpath_context_register_namespaces(VALUE self, VALUE nslist) {
|
188
|
+
char *cp;
|
189
|
+
long i;
|
190
|
+
VALUE rprefix, ruri;
|
191
|
+
|
192
|
+
/* Need to loop through the 2nd argument and iterate through the
|
193
|
+
* list of namespaces that we want to allow */
|
194
|
+
switch (TYPE(nslist)) {
|
195
|
+
case T_STRING:
|
196
|
+
cp = strchr(StringValuePtr(nslist), (int)':');
|
197
|
+
if (cp == NULL) {
|
198
|
+
rprefix = nslist;
|
199
|
+
ruri = Qnil;
|
200
|
+
} else {
|
201
|
+
rprefix = rb_str_new(StringValuePtr(nslist), (int)((long)cp - (long)StringValuePtr(nslist)));
|
202
|
+
ruri = rb_str_new2(&cp[1]);
|
203
|
+
}
|
204
|
+
/* Should test the results of this */
|
205
|
+
ruby_xml_xpath_context_register_namespace(self, rprefix, ruri);
|
206
|
+
break;
|
207
|
+
case T_ARRAY:
|
208
|
+
for (i = 0; i < RARRAY(nslist)->len; i++) {
|
209
|
+
ruby_xml_xpath_context_register_namespaces(self, RARRAY(nslist)->ptr[i]);
|
210
|
+
}
|
211
|
+
break;
|
212
|
+
case T_HASH:
|
213
|
+
st_foreach(RHASH(nslist)->tbl, iterate_ns_hash, self);
|
214
|
+
break;
|
215
|
+
default:
|
216
|
+
rb_raise(rb_eArgError, "Invalid argument type, only accept string, array of strings, or an array of arrays");
|
217
|
+
}
|
218
|
+
return self;
|
219
|
+
}
|
220
|
+
|
221
|
+
/*
|
222
|
+
* call-seq:
|
223
|
+
* context.node = node
|
224
|
+
*
|
225
|
+
* Set the current node used by the XPath engine
|
226
|
+
|
227
|
+
* doc = XML::Document.string('<header><first>hi</first></header>')
|
228
|
+
* context.node = doc.root.first
|
229
|
+
*/
|
230
|
+
VALUE
|
231
|
+
ruby_xml_xpath_context_node_set(VALUE self, VALUE node) {
|
232
|
+
xmlXPathContextPtr xctxt;
|
233
|
+
xmlNodePtr xnode;
|
234
|
+
|
235
|
+
Data_Get_Struct(self, xmlXPathContext, xctxt);
|
236
|
+
Data_Get_Struct(node, xmlNode, xnode);
|
237
|
+
xctxt->node = xnode;
|
238
|
+
return node;
|
239
|
+
}
|
240
|
+
|
241
|
+
/*
|
242
|
+
* call-seq:
|
243
|
+
* context.find("xpath") -> XML::XPath::Object
|
244
|
+
*
|
245
|
+
* Find nodes matching the specified XPath expression
|
246
|
+
*/
|
247
|
+
VALUE
|
248
|
+
ruby_xml_xpath_context_find(VALUE self, VALUE xpath_expr) {
|
249
|
+
xmlXPathContextPtr xctxt;
|
250
|
+
xmlXPathObjectPtr xobject;
|
251
|
+
xmlXPathCompExprPtr xcompexpr;
|
252
|
+
VALUE result;
|
253
|
+
|
254
|
+
Data_Get_Struct(self, xmlXPathContext, xctxt);
|
255
|
+
|
256
|
+
if (TYPE(xpath_expr) == T_STRING) {
|
257
|
+
VALUE expression = rb_check_string_type(xpath_expr);
|
258
|
+
xobject = xmlXPathEval((xmlChar*)StringValueCStr(expression), xctxt);
|
259
|
+
}
|
260
|
+
else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression)) {
|
261
|
+
Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr);
|
262
|
+
xobject = xmlXPathCompiledEval(xcompexpr, xctxt);
|
263
|
+
}
|
264
|
+
else {
|
265
|
+
rb_raise(rb_eTypeError, "Argument should be an intance of a String or XPath::Expression");
|
266
|
+
}
|
267
|
+
|
268
|
+
if (xobject == NULL)
|
269
|
+
{
|
270
|
+
/* xmlLastError is different than xctxt->lastError. Use
|
271
|
+
xmlLastError since it has the message set while xctxt->lastError
|
272
|
+
does not. */
|
273
|
+
xmlErrorPtr xerror = xmlGetLastError();
|
274
|
+
ruby_xml_raise(xerror);
|
275
|
+
}
|
276
|
+
|
277
|
+
result = ruby_xml_xpath_object_wrap(xobject);
|
278
|
+
rb_iv_set(result, "@context", self);
|
279
|
+
return result;
|
280
|
+
}
|
281
|
+
|
282
|
+
|
283
|
+
void
|
284
|
+
ruby_init_xml_xpath_context(void) {
|
285
|
+
cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
|
286
|
+
rb_define_alloc_func(cXMLXPathContext, ruby_xml_xpath_context_alloc);
|
287
|
+
rb_define_attr(cXMLXPathContext, "doc", 1, 0);
|
288
|
+
rb_define_method(cXMLXPathContext, "initialize", ruby_xml_xpath_context_initialize, 1);
|
289
|
+
rb_define_method(cXMLXPathContext, "register_namespaces", ruby_xml_xpath_context_register_namespaces, 1);
|
290
|
+
rb_define_method(cXMLXPathContext, "register_namespaces_from_node", ruby_xml_xpath_context_register_namespaces_from_node, 1);
|
291
|
+
rb_define_method(cXMLXPathContext, "register_namespace", ruby_xml_xpath_context_register_namespace, 2);
|
292
|
+
rb_define_method(cXMLXPathContext, "node=", ruby_xml_xpath_context_node_set, 1);
|
293
|
+
rb_define_method(cXMLXPathContext, "find", ruby_xml_xpath_context_find, 1);
|
294
|
+
}
|