ruby-xpath 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }