ruby-xpath 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation; either version 2 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+ #include "rb_utils.h"
19
+
20
+ char * getRubyObjectName( VALUE rb_Object ) {
21
+ VALUE klass = rb_funcall( rb_Object, rb_intern( "class" ), 0 );
22
+ return( STR2CSTR( rb_funcall( klass, rb_intern( "to_s" ), 0 ) ) );
23
+ }
24
+
25
+ int isFile( const char *filename ) {
26
+ struct stat stbuf;
27
+
28
+ if (stat(filename, &stbuf)) return 0;
29
+ return ((stbuf.st_mode & S_IFMT) == S_IFREG) ? 1 : 0;
30
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation; either version 2 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ /* Please see the LICENSE file for copyright and distribution information */
20
+
21
+ #ifndef __RUBY_RB_UTILS_H__
22
+ #define __RUBY_RB_UTILS_H__
23
+
24
+ #include <ruby.h>
25
+ #include <rubyio.h>
26
+
27
+ #include <stdio.h>
28
+ #include <string.h>
29
+ #include <sys/stat.h>
30
+
31
+ char * getRubyObjectName( VALUE );
32
+ int isFile( const char *filename );
33
+
34
+ #endif
@@ -0,0 +1,535 @@
1
+ /**
2
+ * Copyright (C) 2004, 2005 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation; either version 2 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "xpath.h"
20
+
21
+ static VALUE each_pair( VALUE obj ) {
22
+ return rb_funcall( obj, rb_intern("each"), 0, 0 );
23
+ }
24
+
25
+ static VALUE process_pair( VALUE pair, VALUE rbparams ) {
26
+ VALUE key, value;
27
+ static int count = 0;
28
+
29
+ Check_Type(pair, T_ARRAY);
30
+
31
+ key = RARRAY(pair)->ptr[0];
32
+ value = RARRAY(pair)->ptr[1];
33
+
34
+ Check_Type(key, T_STRING);
35
+ Check_Type(value, T_STRING);
36
+
37
+ rb_ary_store( rbparams, count, key );
38
+ rb_ary_store( rbparams, count + 1, value );
39
+
40
+ count += 2;
41
+ return Qnil;
42
+ }
43
+
44
+ /* ------------------------------------------------------------------------------- */
45
+
46
+ /**
47
+ * register_namespaces:
48
+ * @xpathCtx: the pointer to an XPath context.
49
+ * @nsList: the list of known namespaces in
50
+ * {<prefix1>=><href1>, <prefix2>=>href2>, ...} format.
51
+ *
52
+ * Registers namespaces from @nsList in @xpathCtx.
53
+ *
54
+ * Returns 0 on success and a negative value otherwise.
55
+ */
56
+ int register_namespaces( xmlXPathContextPtr xpathCtx, VALUE nsList ) {
57
+ xmlChar* prefix;
58
+ xmlChar* href;
59
+ int iNbNs;
60
+ int iCpt;
61
+
62
+ VALUE lxNS = rb_ary_new( );
63
+ (void)rb_iterate( each_pair, nsList, process_pair, lxNS );
64
+ iNbNs = FIX2INT( rb_funcall( nsList, rb_intern("size"), 0, 0 ) );
65
+
66
+ for( iCpt = 0; iCpt <= iNbNs; iCpt += 2 ) {
67
+ prefix = (xmlChar*)STR2CSTR( rb_ary_entry( lxNS, iCpt ) );
68
+ href = (xmlChar*)STR2CSTR( rb_ary_entry( lxNS, iCpt+1 ) );
69
+
70
+ if( xmlXPathRegisterNs( xpathCtx, prefix, href ) != 0 ) {
71
+ return( -1 );
72
+ }
73
+ }
74
+
75
+ return( 0 );
76
+ }
77
+
78
+ int get_xpath_nodes( xmlNodeSetPtr nodes, RbTxpath *pRbTxpath ) {
79
+ int RCod;
80
+ int iCpt;
81
+ int jCpt;
82
+ struct _xmlAttr *attr;
83
+ VALUE rbNode;
84
+ VALUE rbListAttr;
85
+
86
+ pRbTxpath->rbResult = rb_ary_new( );
87
+
88
+ RCod = pRbTxpath->iNbNodes = (nodes) ? nodes->nodeNr : 0;
89
+ pRbTxpath->iCurrentNode = 0;
90
+
91
+ for( iCpt = 0; iCpt < RCod; iCpt++ ) {
92
+ rbNode = rb_hash_new( );
93
+
94
+ rb_hash_aset( rbNode, rb_str_new2( "type" ), INT2NUM( (int)nodes->nodeTab[iCpt]->type ) );
95
+ rb_hash_aset( rbNode, rb_str_new2( "path" ), rb_str_new2( (char*)xmlGetNodePath(nodes->nodeTab[iCpt]) ) );
96
+ rb_hash_aset( rbNode, rb_str_new2( "name" ), rb_str_new2( (char*)nodes->nodeTab[iCpt]->name ) );
97
+
98
+ if( nodes->nodeTab[iCpt]->ns != NULL ) {
99
+ rb_hash_aset( rbNode, rb_str_new2( "NS href" ), rb_str_new2( (char*)nodes->nodeTab[iCpt]->ns->href ) );
100
+ rb_hash_aset( rbNode, rb_str_new2( "NS prefix" ), rb_str_new2( (char*)nodes->nodeTab[iCpt]->ns->prefix ) );
101
+ }
102
+
103
+ switch( nodes->nodeTab[iCpt]->type ) {
104
+ case XML_ELEMENT_NODE:
105
+ rbListAttr = rb_hash_new( );
106
+
107
+ jCpt = 0;
108
+ if( nodes->nodeTab[iCpt]->children != NULL && nodes->nodeTab[iCpt]->children->content != NULL ) {
109
+ rb_hash_aset( rbNode, rb_str_new2( "content" ), rb_str_new2( (char*)nodes->nodeTab[iCpt]->children->content ) );
110
+ }
111
+
112
+ attr = nodes->nodeTab[iCpt]->properties;
113
+ while( attr != NULL ) {
114
+ rb_hash_aset( rbListAttr, rb_str_new2( (char*)attr->name ), rb_str_new2( (char*)attr->children->content ) );
115
+
116
+ jCpt++;
117
+ attr = attr->next;
118
+ }
119
+
120
+ if( jCpt > 0 ) {
121
+ rb_hash_aset( rbNode, rb_str_new2( "attrs" ), rbListAttr );
122
+ }
123
+ break;
124
+
125
+ case XML_ATTRIBUTE_NODE:
126
+ if( nodes->nodeTab[iCpt]->children != NULL ) {
127
+ rb_hash_aset( rbNode, rb_str_new2( "content" ), rb_str_new2( (char*)nodes->nodeTab[iCpt]->children->content ) );
128
+ }
129
+ break;
130
+
131
+ default:
132
+ break;
133
+ }
134
+
135
+ rb_ary_push( pRbTxpath->rbResult, rbNode );
136
+ }
137
+
138
+ return( RCod );
139
+ }
140
+
141
+ /**
142
+ * execute_xpath_expression:
143
+ *
144
+ * Parses input XML file, evaluates XPath expression and return results.
145
+ *
146
+ * Returns 0 on success and a negative value otherwise.
147
+ */
148
+ int parse( const char* xml, int iXmlType, const xmlChar* xpathExpr, RbTxpath *pRbTxpath ) {
149
+ xmlErrorPtr ptXMLError;
150
+ xmlDocPtr doc = NULL;
151
+ xmlXPathContextPtr xpathCtx;
152
+ xmlXPathObjectPtr xpathObj;
153
+ int RCod = -1;
154
+
155
+ /* Init libxml */
156
+ xmlInitParser();
157
+ LIBXML_TEST_VERSION
158
+
159
+ /** Act: Parse XML */
160
+ xmlResetLastError( );
161
+ ptXMLError = NULL;
162
+ if( iXmlType == RUBY_XPATH_XMLSRC_TYPE_STR ) {
163
+ doc = xmlParseMemory( xml, strlen( xml ) );
164
+ } else if( iXmlType == RUBY_XPATH_XMLSRC_TYPE_FILE ) {
165
+ doc = xmlParseFile( xml );
166
+ }
167
+
168
+ ptXMLError = xmlGetLastError();
169
+ if( doc == NULL || ptXMLError != NULL ) {
170
+ rb_fatal( "XML::XPATH: XML parsing error : %s\n", ptXMLError->message );
171
+ return( RCod );
172
+ }
173
+
174
+ /* Create xpath evaluation context */
175
+ xpathCtx = xmlXPathNewContext(doc);
176
+ if(xpathCtx == NULL) {
177
+ ptXMLError = xmlGetLastError();
178
+ rb_fatal( "Error: unable to create new XPath context : %s\n", ptXMLError->message);
179
+ xmlFreeDoc(doc);
180
+ return( RCod );
181
+ }
182
+
183
+ /* Register namespaces from list (if any) */
184
+ if( pRbTxpath->hxNS != Qnil ) {
185
+ if( register_namespaces(xpathCtx, pRbTxpath->hxNS) < 0 ) {
186
+ ptXMLError = xmlGetLastError();
187
+ rb_fatal( "Error: failed to register namespaces list : %s\n", ptXMLError->message );
188
+ xmlXPathFreeContext(xpathCtx);
189
+ xmlFreeDoc(doc);
190
+ return( RCod );
191
+ }
192
+ }
193
+
194
+ /* Evaluate xpath expression */
195
+ xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
196
+ if(xpathObj == NULL) {
197
+ ptXMLError = xmlGetLastError();
198
+ rb_fatal("Error: unable to evaluate xpath expression \"%s\" : %s\n", xpathExpr, ptXMLError->message );
199
+ xmlXPathFreeContext(xpathCtx);
200
+ xmlFreeDoc(doc);
201
+ return( RCod );
202
+ }
203
+
204
+ /* Print results */
205
+ RCod = get_xpath_nodes( xpathObj->nodesetval, pRbTxpath );
206
+
207
+ /* Cleanup */
208
+ xmlXPathFreeObject(xpathObj);
209
+ xmlXPathFreeContext(xpathCtx);
210
+ xmlFreeDoc(doc);
211
+
212
+ /* Shutdown libxml */
213
+ xmlCleanupParser();
214
+
215
+ /*
216
+ * this is to debug memory for regression tests
217
+ */
218
+ xmlMemoryDump();
219
+ return( RCod );
220
+ }
221
+
222
+ VALUE get_node_element( VALUE self, const char *xField ) {
223
+ RbTxpath *pRbTxpath;
224
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
225
+ VALUE xValue = Qnil;
226
+
227
+ if( pRbTxpath->iNbNodes > 0 ) {
228
+ VALUE rbNode = rb_ary_entry( pRbTxpath->rbResult, pRbTxpath->iCurrentNode );
229
+ xValue = rb_hash_aref( rbNode, rb_str_new2( xField ) );
230
+ }
231
+
232
+ return( xValue );
233
+ }
234
+
235
+ /**
236
+ * vOut = object_to_string( VALUE object );
237
+ */
238
+ VALUE object_to_string( VALUE object ) {
239
+ VALUE vOut = Qnil;
240
+
241
+ switch( TYPE( object ) ) {
242
+ case T_STRING:
243
+ {
244
+ if( isFile( STR2CSTR( object ) ) == 0 ) {
245
+ vOut = object;
246
+ } else {
247
+ long iBufferLength;
248
+ long iCpt;
249
+ char *xBuffer;
250
+
251
+ FILE* fStream = fopen( STR2CSTR( object ), "r" );
252
+ if( fStream == NULL ) {
253
+ return( Qnil );
254
+ }
255
+
256
+ fseek( fStream, 0L, 2 );
257
+ iBufferLength = ftell( fStream );
258
+ xBuffer = (char *)malloc( (int)iBufferLength + 1 );
259
+ if( !xBuffer )
260
+ rb_raise( rb_eNoMemError, "Memory allocation error" );
261
+
262
+ xBuffer[iBufferLength] = 0;
263
+ fseek( fStream, 0L, 0 );
264
+ iCpt = fread( xBuffer, 1, (int)iBufferLength, fStream );
265
+
266
+ if( iCpt != iBufferLength ) {
267
+ free( (char *)xBuffer );
268
+ rb_raise( rb_eSystemCallError, "Read file error" );
269
+ }
270
+
271
+ vOut = rb_str_new2( xBuffer );
272
+
273
+ fclose( fStream );
274
+ }
275
+ }
276
+ break;
277
+
278
+ case T_DATA:
279
+ case T_OBJECT:
280
+ {
281
+ if( strcmp( getRubyObjectName( object ), "XML::Simple::Dom" ) == 0 ) {
282
+ vOut = rb_funcall( object, rb_intern( "to_s" ), 0 );
283
+ } else {
284
+ rb_raise( rb_eSystemCallError, "Can't read XML from object %s", getRubyObjectName( object ) );
285
+ }
286
+ }
287
+ break;
288
+
289
+ default:
290
+ rb_raise( rb_eArgError, "XML object #0x%x not supported", TYPE( object ) );
291
+ }
292
+
293
+ return( vOut );
294
+ }
295
+
296
+ /* ------------------------------------------------------------------------------- */
297
+
298
+ /** xmlData = o.xml */
299
+ VALUE ruby_xpath_xml_str_get( VALUE self ) {
300
+ RbTxpath *pRbTxpath;
301
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
302
+
303
+ if( pRbTxpath->iXmlType == RUBY_XPATH_XMLSRC_TYPE_NULL )
304
+ return( Qnil );
305
+ else
306
+ return( (VALUE)pRbTxpath->xXmlData );
307
+ }
308
+
309
+ /** o.xml = "<...>" */
310
+ VALUE ruby_xpath_xml_str_set( VALUE self, VALUE xml_doc_str ) {
311
+ RbTxpath *pRbTxpath;
312
+
313
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
314
+
315
+ pRbTxpath->iXmlType = RUBY_XPATH_XMLSRC_TYPE_STR;
316
+ pRbTxpath->xXmlData = object_to_string( xml_doc_str );
317
+
318
+ return( xml_doc_str );
319
+ }
320
+
321
+ /** o.xmlfile="file.xml" */
322
+ VALUE ruby_xpath_xml_file_set( VALUE self, VALUE xml_doc_file ) {
323
+ rb_warn( "XML::XSLT#xmlfile=<file> is deprecated. Please use XML::XSLT#xml=<file> !" );
324
+ return( ruby_xpath_xml_str_set( self, xml_doc_file ) );
325
+ }
326
+
327
+ /** o.ns={ ... } */
328
+ VALUE ruby_xpath_xml_ns_set( VALUE self, VALUE ns_hash ) {
329
+ RbTxpath *pRbTxpath;
330
+ Check_Type( ns_hash, T_HASH );
331
+
332
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
333
+ pRbTxpath->hxNS = ns_hash;
334
+
335
+ return( Qnil );
336
+ }
337
+
338
+ /* ------------------------------------------------------------------------------- */
339
+
340
+ /** o.execute( XPathExp ) */
341
+ VALUE ruby_xpath_xml_execute( VALUE self, VALUE xpathExp ) {
342
+ int RCod = -1;
343
+ RbTxpath *pRbTxpath;
344
+ Check_Type( xpathExp, T_STRING );
345
+
346
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
347
+
348
+ RCod = parse( STR2CSTR( pRbTxpath->xXmlData ), pRbTxpath->iXmlType, BAD_CAST STR2CSTR( xpathExp ), pRbTxpath );
349
+
350
+ return( INT2NUM( RCod ) );
351
+ }
352
+
353
+ /* a = o.to_a */
354
+ VALUE ruby_xpath_xml_to_a( VALUE self ) {
355
+ RbTxpath *pRbTxpath;
356
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
357
+
358
+ return( pRbTxpath->rbResult );
359
+ }
360
+
361
+ /* ------------------------------------------------------------------------------- */
362
+
363
+ VALUE ruby_xpath_xml_each( VALUE self ) {
364
+ RbTxpath *pRbTxpath;
365
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
366
+ int iCpt;
367
+
368
+ if (rb_block_given_p()) {
369
+ for( iCpt = 0; iCpt < pRbTxpath->iNbNodes; iCpt++ ) {
370
+ VALUE rbNode = rb_ary_entry( pRbTxpath->rbResult, iCpt );
371
+ rb_yield( rbNode );
372
+ }
373
+ }
374
+ return( Qnil );
375
+ }
376
+
377
+ VALUE ruby_xpath_xml_first( VALUE self ) {
378
+ RbTxpath *pRbTxpath;
379
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
380
+ int RCod = 0;
381
+
382
+ if( pRbTxpath->iNbNodes > 0 ) {
383
+ pRbTxpath->iCurrentNode = 0;
384
+ RCod = 1;
385
+ }
386
+
387
+ return( INT2NUM( RCod ) );
388
+ }
389
+
390
+ VALUE ruby_xpath_xml_last( VALUE self ) {
391
+ RbTxpath *pRbTxpath;
392
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
393
+ int RCod = 0;
394
+
395
+ if( pRbTxpath->iNbNodes > 0 ) {
396
+ pRbTxpath->iCurrentNode = pRbTxpath->iNbNodes - 1;
397
+ RCod = pRbTxpath->iNbNodes;
398
+ }
399
+
400
+ return( INT2NUM( RCod ) );
401
+ }
402
+
403
+ VALUE ruby_xpath_xml_next( VALUE self ) {
404
+ RbTxpath *pRbTxpath;
405
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
406
+ int RCod = 0;
407
+
408
+ if( pRbTxpath->iCurrentNode + 1 < pRbTxpath->iNbNodes ) {
409
+ pRbTxpath->iCurrentNode += 1;
410
+ RCod = pRbTxpath->iCurrentNode + 1;
411
+ }
412
+
413
+ return( INT2NUM( RCod ) );
414
+ }
415
+
416
+ VALUE ruby_xpath_xml_prev( VALUE self ) {
417
+ RbTxpath *pRbTxpath;
418
+ Data_Get_Struct( self, RbTxpath, pRbTxpath );
419
+ int RCod = 0;
420
+
421
+ if( pRbTxpath->iCurrentNode - 1 >= 0 ) {
422
+ pRbTxpath->iCurrentNode -= 1;
423
+ RCod = pRbTxpath->iCurrentNode + 1;
424
+ }
425
+
426
+ return( INT2NUM( RCod ) );
427
+ }
428
+
429
+ /* ------------------------------------------------------------------------------- */
430
+
431
+ VALUE ruby_xpath_xml_name( VALUE self ) {
432
+ return( get_node_element( self, "name" ) );
433
+ }
434
+
435
+ VALUE ruby_xpath_xml_attrs( VALUE self ) {
436
+ return( get_node_element( self, "attrs" ) );
437
+ }
438
+
439
+ VALUE ruby_xpath_xml_type( VALUE self ) {
440
+ return( get_node_element( self, "type" ) );
441
+ }
442
+
443
+ VALUE ruby_xpath_xml_content( VALUE self ) {
444
+ return( get_node_element( self, "content" ) );
445
+ }
446
+
447
+ VALUE ruby_xpath_xml_path( VALUE self ) {
448
+ return( get_node_element( self, "path" ) );
449
+ }
450
+
451
+
452
+ /* ------------------------------------------------------------------------------- */
453
+
454
+ void ruby_xpath_free( RbTxpath *pRbTxpath ) {
455
+ if (pRbTxpath != NULL)
456
+ free(pRbTxpath);
457
+ }
458
+
459
+ void ruby_xpath_mark( RbTxpath *pRbTxpath ) {
460
+ if( pRbTxpath == NULL ) return;
461
+ if( !NIL_P(pRbTxpath->xXmlData) ) rb_gc_mark( pRbTxpath->xXmlData );
462
+ if( !NIL_P(pRbTxpath->hxNS) ) rb_gc_mark( pRbTxpath->hxNS );
463
+ if( !NIL_P(pRbTxpath->rbResult) ) rb_gc_mark( pRbTxpath->rbResult );
464
+ }
465
+
466
+ /** o = XML::XPATH.new() */
467
+ VALUE ruby_xpath_new( VALUE class ) {
468
+ RbTxpath *pRbTxpath;
469
+
470
+ pRbTxpath = (RbTxpath *)malloc(sizeof(RbTxpath));
471
+ if( pRbTxpath == NULL )
472
+ rb_raise(rb_eNoMemError, "No memory left for XPATH struct");
473
+
474
+ pRbTxpath->iXmlType = RUBY_XPATH_XMLSRC_TYPE_NULL;
475
+ pRbTxpath->xXmlData = Qnil;
476
+ pRbTxpath->hxNS = Qnil;
477
+ pRbTxpath->rbResult = Qnil;
478
+ pRbTxpath->iCurrentNode = 0;
479
+ pRbTxpath->iNbNodes = 0;
480
+
481
+ return( Data_Wrap_Struct( class, ruby_xpath_mark, ruby_xpath_free, pRbTxpath ) );
482
+ }
483
+
484
+ VALUE mXML;
485
+ VALUE cXPATH;
486
+
487
+ void Init_xpath( void ) {
488
+ mXML = rb_define_module( "XML" );
489
+ cXPATH = rb_define_class_under( mXML, "XPATH", rb_cObject );
490
+
491
+ rb_define_const( cXPATH, "XML_ELEMENT_NODE", INT2NUM( 1 ) );
492
+ rb_define_const( cXPATH, "XML_ATTRIBUTE_NODE", INT2NUM( 2 ) );
493
+ rb_define_const( cXPATH, "XML_TEXT_NODE", INT2NUM( 3 ) );
494
+ rb_define_const( cXPATH, "XML_CDATA_SECTION_NODE", INT2NUM( 4 ) );
495
+ rb_define_const( cXPATH, "XML_ENTITY_REF_NODE", INT2NUM( 5 ) );
496
+ rb_define_const( cXPATH, "XML_ENTITY_NODE", INT2NUM( 6 ) );
497
+ rb_define_const( cXPATH, "XML_PI_NODE", INT2NUM( 7 ) );
498
+ rb_define_const( cXPATH, "XML_COMMENT_NODE", INT2NUM( 8 ) );
499
+ rb_define_const( cXPATH, "XML_DOCUMENT_NODE", INT2NUM( 9 ) );
500
+ rb_define_const( cXPATH, "XML_DOCUMENT_TYPE_NODE", INT2NUM( 10 ) );
501
+ rb_define_const( cXPATH, "XML_DOCUMENT_FRAG_NODE", INT2NUM( 11 ) );
502
+ rb_define_const( cXPATH, "XML_NOTATION_NODE", INT2NUM( 12 ) );
503
+ rb_define_const( cXPATH, "XML_HTML_DOCUMENT_NODE", INT2NUM( 13 ) );
504
+ rb_define_const( cXPATH, "XML_DTD_NODE", INT2NUM( 14 ) );
505
+ rb_define_const( cXPATH, "XML_ELEMENT_DECL", INT2NUM( 15 ) );
506
+ rb_define_const( cXPATH, "XML_ATTRIBUTE_DECL", INT2NUM( 16 ) );
507
+ rb_define_const( cXPATH, "XML_ENTITY_DECL", INT2NUM( 17 ) );
508
+ rb_define_const( cXPATH, "XML_NAMESPACE_DECL", INT2NUM( 18 ) );
509
+ rb_define_const( cXPATH, "XML_XINCLUDE_START", INT2NUM( 19 ) );
510
+ rb_define_const( cXPATH, "XML_XINCLUDE_END", INT2NUM( 20 ) );
511
+ rb_define_const( cXPATH, "XML_DOCB_DOCUMENT_NODE", INT2NUM( 21 ) );
512
+ rb_define_const( cXPATH, "RUBY_XPATH_VERSION", rb_str_new2( RUBY_XPATH_VERSION ) );
513
+
514
+ rb_define_singleton_method( cXPATH, "new", ruby_xpath_new, 0 );
515
+
516
+ rb_define_method( cXPATH, "xml", ruby_xpath_xml_str_get, 0 );
517
+ rb_define_method( cXPATH, "xml=", ruby_xpath_xml_str_set, 1 );
518
+ rb_define_method( cXPATH, "xmlfile=", ruby_xpath_xml_file_set, 1 ); // DEPRECATED
519
+ rb_define_method( cXPATH, "ns=", ruby_xpath_xml_ns_set, 1 );
520
+
521
+ rb_define_method( cXPATH, "execute", ruby_xpath_xml_execute, 1 );
522
+ rb_define_method( cXPATH, "to_a", ruby_xpath_xml_to_a, 0 );
523
+
524
+ rb_define_method( cXPATH, "each", ruby_xpath_xml_each, 0 );
525
+ rb_define_method( cXPATH, "first", ruby_xpath_xml_first, 0 );
526
+ rb_define_method( cXPATH, "last", ruby_xpath_xml_last, 0 );
527
+ rb_define_method( cXPATH, "next", ruby_xpath_xml_next, 0 );
528
+ rb_define_method( cXPATH, "prev", ruby_xpath_xml_prev, 0 );
529
+
530
+ rb_define_method( cXPATH, "name", ruby_xpath_xml_name, 0 );
531
+ rb_define_method( cXPATH, "attrs", ruby_xpath_xml_attrs, 0 );
532
+ rb_define_method( cXPATH, "type", ruby_xpath_xml_type, 0 );
533
+ rb_define_method( cXPATH, "content", ruby_xpath_xml_content, 0 );
534
+ rb_define_method( cXPATH, "path", ruby_xpath_xml_path, 0 );
535
+ }