libxml-ruby 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/CHANGES +13 -0
  2. data/ext/libxml/libxml.c +885 -886
  3. data/ext/libxml/ruby_libxml.h +70 -72
  4. data/ext/libxml/ruby_xml_attr.c +76 -76
  5. data/ext/libxml/ruby_xml_attr.h +8 -8
  6. data/ext/libxml/ruby_xml_attributes.c +36 -36
  7. data/ext/libxml/ruby_xml_attributes.h +6 -6
  8. data/ext/libxml/ruby_xml_document.c +133 -220
  9. data/ext/libxml/ruby_xml_document.h +4 -7
  10. data/ext/libxml/ruby_xml_dtd.c +30 -109
  11. data/ext/libxml/ruby_xml_dtd.h +2 -11
  12. data/ext/libxml/ruby_xml_error.c +10 -10
  13. data/ext/libxml/ruby_xml_error.h +4 -4
  14. data/ext/libxml/ruby_xml_html_parser.c +28 -40
  15. data/ext/libxml/ruby_xml_html_parser.h +4 -4
  16. data/ext/libxml/ruby_xml_input.c +208 -32
  17. data/ext/libxml/ruby_xml_input.h +7 -5
  18. data/ext/libxml/ruby_xml_input_cbg.c +3 -3
  19. data/ext/libxml/ruby_xml_node.c +217 -217
  20. data/ext/libxml/ruby_xml_node.h +5 -5
  21. data/ext/libxml/ruby_xml_ns.c +26 -26
  22. data/ext/libxml/ruby_xml_ns.h +4 -4
  23. data/ext/libxml/ruby_xml_parser.c +151 -164
  24. data/ext/libxml/ruby_xml_parser.h +3 -8
  25. data/ext/libxml/ruby_xml_parser_context.c +105 -105
  26. data/ext/libxml/ruby_xml_parser_context.h +4 -4
  27. data/ext/libxml/ruby_xml_reader.c +145 -162
  28. data/ext/libxml/ruby_xml_reader.h +4 -4
  29. data/ext/libxml/ruby_xml_relaxng.c +30 -43
  30. data/ext/libxml/ruby_xml_relaxng.h +2 -7
  31. data/ext/libxml/ruby_xml_sax_parser.c +174 -228
  32. data/ext/libxml/ruby_xml_sax_parser.h +12 -20
  33. data/ext/libxml/ruby_xml_schema.c +31 -44
  34. data/ext/libxml/ruby_xml_schema.h +2 -7
  35. data/ext/libxml/ruby_xml_state.c +6 -6
  36. data/ext/libxml/ruby_xml_state.h +2 -2
  37. data/ext/libxml/ruby_xml_xinclude.c +1 -1
  38. data/ext/libxml/ruby_xml_xinclude.h +3 -3
  39. data/ext/libxml/ruby_xml_xpath.c +1 -1
  40. data/ext/libxml/ruby_xml_xpath.h +3 -12
  41. data/ext/libxml/ruby_xml_xpath_context.c +293 -294
  42. data/ext/libxml/ruby_xml_xpath_context.h +3 -7
  43. data/ext/libxml/ruby_xml_xpath_expression.c +11 -11
  44. data/ext/libxml/ruby_xml_xpath_expression.h +2 -2
  45. data/ext/libxml/ruby_xml_xpath_object.c +52 -66
  46. data/ext/libxml/ruby_xml_xpath_object.h +3 -14
  47. data/ext/libxml/ruby_xml_xpointer.c +11 -12
  48. data/ext/libxml/ruby_xml_xpointer.h +5 -7
  49. data/ext/libxml/sax_parser_callbacks.inc +53 -36
  50. data/ext/libxml/version.h +2 -2
  51. data/ext/vc/libxml_ruby.vcproj +1 -9
  52. data/lib/libxml/html_parser.rb +5 -5
  53. data/lib/libxml/parser.rb +4 -4
  54. data/lib/libxml/sax_parser.rb +24 -0
  55. data/test/tc_document_write.rb +2 -16
  56. data/test/tc_html_parser.rb +57 -5
  57. data/test/tc_input.rb +13 -0
  58. data/test/tc_parser.rb +11 -3
  59. data/test/tc_reader.rb +53 -34
  60. data/test/tc_sax_parser.rb +30 -8
  61. data/test/test.rb +8 -0
  62. data/test/test_suite.rb +1 -1
  63. metadata +5 -6
  64. data/ext/libxml/ruby_xml_encoding.c +0 -164
  65. data/ext/libxml/ruby_xml_encoding.h +0 -13
  66. data/test/tc_encoding.rb +0 -13
@@ -1,20 +1,12 @@
1
- /* $Id: ruby_xml_sax_parser.h 544 2008-11-16 09:50:27Z cfis $ */
2
-
3
- /* Please see the LICENSE file for copyright and distribution information */
4
-
5
- #ifndef __RUBY_XML_SAX_PARSER__
6
- #define __RUBY_XML_SAX_PARSER__
7
-
8
- extern VALUE cXMLSaxParser;
9
-
10
- typedef struct ruby_xml_sax_parser {
11
- xmlParserCtxtPtr xpc;
12
- xmlSAXHandlerPtr xsh;
13
- VALUE callbackHandler;
14
- VALUE filename;
15
- VALUE str;
16
- } ruby_xml_sax_parser;
17
-
18
- void ruby_init_xml_sax_parser(void);
19
-
20
- #endif
1
+ /* $Id: ruby_xml_sax_parser.h 616 2008-11-22 09:25:12Z cfis $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __rxml_SAX_PARSER__
6
+ #define __rxml_SAX_PARSER__
7
+
8
+ extern VALUE cXMLSaxParser;
9
+
10
+ void ruby_init_xml_sax_parser(void);
11
+
12
+ #endif
@@ -39,39 +39,28 @@ VALUE cXMLSchema;
39
39
  #endif
40
40
 
41
41
  static void
42
- ruby_xml_schema_mark(ruby_xml_schema *rxschema) {
43
- return;
44
- }
45
-
46
- void
47
- ruby_xml_schema_free(ruby_xml_schema *rxschema) {
48
- if (rxschema->schema != NULL) {
49
- xmlSchemaFree(rxschema->schema);
50
- rxschema->schema = NULL;
51
- }
52
-
53
- ruby_xfree(rxschema);
42
+ rxml_schema_free(xmlSchemaPtr xschema) {
43
+ xmlSchemaFree(xschema);
54
44
  }
55
45
 
56
46
  /*
57
47
  * call-seq:
58
- * XML::Schema.new(schema_uri) -> schema
48
+ * XML::Schema.initialize(schema_uri) -> schema
59
49
  *
60
50
  * Create a new schema from the specified URI.
61
51
  */
62
- VALUE
63
- ruby_xml_schema_init_from_uri(VALUE class, VALUE uri) {
64
- xmlSchemaParserCtxtPtr parser;
65
- ruby_xml_schema *schema;
52
+ static VALUE
53
+ rxml_schema_init_from_uri(VALUE class, VALUE uri) {
54
+ xmlSchemaParserCtxtPtr xparser;
55
+ xmlSchemaPtr xschema;
66
56
 
67
57
  Check_Type(uri, T_STRING);
68
58
 
69
- parser = xmlSchemaNewParserCtxt(StringValuePtr(uri));
70
- schema = ALLOC(ruby_xml_schema);
71
- schema->schema = xmlSchemaParse(parser);
72
- xmlSchemaFreeParserCtxt(parser);
73
-
74
- return Data_Wrap_Struct(cXMLSchema, ruby_xml_schema_mark, ruby_xml_schema_free, schema);
59
+ xparser = xmlSchemaNewParserCtxt(StringValuePtr(uri));
60
+ xschema = xmlSchemaParse(xparser);
61
+ xmlSchemaFreeParserCtxt(xparser);
62
+
63
+ return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema);
75
64
  }
76
65
 
77
66
  /*
@@ -80,20 +69,19 @@ ruby_xml_schema_init_from_uri(VALUE class, VALUE uri) {
80
69
  *
81
70
  * Create a new schema from the specified document.
82
71
  */
83
- VALUE
84
- ruby_xml_schema_init_from_document(VALUE class, VALUE document) {
72
+ static VALUE
73
+ rxml_schema_init_from_document(VALUE class, VALUE document) {
85
74
  xmlDocPtr xdoc;
86
- ruby_xml_schema *schema;
87
- xmlSchemaParserCtxtPtr parser;
75
+ xmlSchemaPtr xschema;
76
+ xmlSchemaParserCtxtPtr xparser;
88
77
 
89
78
  Data_Get_Struct(document, xmlDoc, xdoc);
90
79
 
91
- parser = xmlSchemaNewDocParserCtxt(xdoc);
92
- schema = ALLOC(ruby_xml_schema);
93
- schema->schema = xmlSchemaParse(parser);
94
- xmlSchemaFreeParserCtxt(parser);
80
+ xparser = xmlSchemaNewDocParserCtxt(xdoc);
81
+ xschema = xmlSchemaParse(xparser);
82
+ xmlSchemaFreeParserCtxt(xparser);
95
83
 
96
- return Data_Wrap_Struct(cXMLSchema, ruby_xml_schema_mark, ruby_xml_schema_free, schema);
84
+ return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema);
97
85
  }
98
86
 
99
87
  /*
@@ -102,19 +90,18 @@ ruby_xml_schema_init_from_document(VALUE class, VALUE document) {
102
90
  *
103
91
  * Create a new schema using the specified string.
104
92
  */
105
- VALUE
106
- ruby_xml_schema_init_from_string(VALUE self, VALUE schema_str) {
107
- xmlSchemaParserCtxtPtr parser;
108
- ruby_xml_schema *rxschema;
93
+ static VALUE
94
+ rxml_schema_init_from_string(VALUE self, VALUE schema_str) {
95
+ xmlSchemaParserCtxtPtr xparser;
96
+ xmlSchemaPtr xschema;
109
97
 
110
98
  Check_Type(schema_str, T_STRING);
111
99
 
112
- parser = xmlSchemaNewMemParserCtxt(StringValuePtr(schema_str), strlen(StringValuePtr(schema_str)));
113
- rxschema = ALLOC(ruby_xml_schema);
114
- rxschema->schema = xmlSchemaParse(parser);
115
- xmlSchemaFreeParserCtxt(parser);
100
+ xparser = xmlSchemaNewMemParserCtxt(StringValuePtr(schema_str), strlen(StringValuePtr(schema_str)));
101
+ xschema = xmlSchemaParse(xparser);
102
+ xmlSchemaFreeParserCtxt(xparser);
116
103
 
117
- return Data_Wrap_Struct(cXMLSchema, ruby_xml_schema_mark, ruby_xml_schema_free, rxschema);
104
+ return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema);
118
105
  }
119
106
 
120
107
  /* TODO what is this patch doing here?
@@ -167,8 +154,8 @@ ruby_xml_schema_init_from_string(VALUE self, VALUE schema_str) {
167
154
 
168
155
  void ruby_init_xml_schema(void) {
169
156
  cXMLSchema = rb_define_class_under(mXML, "Schema", rb_cObject);
170
- rb_define_singleton_method(cXMLSchema, "new", ruby_xml_schema_init_from_uri, 1);
171
- rb_define_singleton_method(cXMLSchema, "from_string", ruby_xml_schema_init_from_string, 1);
172
- rb_define_singleton_method(cXMLSchema, "document", ruby_xml_schema_init_from_document, 1);
157
+ rb_define_singleton_method(cXMLSchema, "new", rxml_schema_init_from_uri, 1);
158
+ rb_define_singleton_method(cXMLSchema, "from_string", rxml_schema_init_from_string, 1);
159
+ rb_define_singleton_method(cXMLSchema, "document", rxml_schema_init_from_document, 1);
173
160
  }
174
161
 
@@ -1,16 +1,11 @@
1
- #ifndef __RUBY_XML_SCHEMA__
2
- #define __RUBY_XML_SCHEMA__
1
+ #ifndef __rxml_SCHEMA__
2
+ #define __rxml_SCHEMA__
3
3
 
4
4
  #include <libxml/schemasInternals.h>
5
5
  #include <libxml/xmlschemas.h>
6
6
 
7
7
  extern VALUE cXMLSchema;
8
8
 
9
- typedef struct rxp_schema {
10
- xmlSchemaPtr schema; /* Schema interface */
11
- } ruby_xml_schema;
12
-
13
9
  void ruby_init_xml_schema(void);
14
- void ruby_schema_free(ruby_xml_schema *rxs);
15
10
  #endif
16
11
 
@@ -7,14 +7,14 @@ VALUE LIBXML_STATE = Qnil;
7
7
 
8
8
  static int dummy = 0;
9
9
 
10
- void
11
- ruby_xml_state_free(int dummy) {
10
+ static void
11
+ rxml_state_free(int dummy) {
12
12
  xmlCleanupParser();
13
13
  LIBXML_STATE = Qnil;
14
14
  }
15
15
 
16
- VALUE
17
- ruby_xml_state_alloc(VALUE klass) {
16
+ static VALUE
17
+ rxml_state_alloc(VALUE klass) {
18
18
  #ifdef DEBUG
19
19
  fprintf(stderr, "Allocating state");
20
20
  #endif
@@ -22,7 +22,7 @@ ruby_xml_state_alloc(VALUE klass) {
22
22
  xmlInitParser();
23
23
 
24
24
  return Data_Wrap_Struct(cXMLState,
25
- NULL, ruby_xml_state_free,
25
+ NULL, rxml_state_free,
26
26
  &dummy);
27
27
  }
28
28
 
@@ -42,7 +42,7 @@ ruby_init_state(void) {
42
42
  rb_mSingleton = rb_const_get(rb_cObject, rb_intern("Singleton"));
43
43
  rb_include_module(cXMLState, rb_mSingleton);
44
44
 
45
- rb_define_alloc_func(cXMLState, ruby_xml_state_alloc);
45
+ rb_define_alloc_func(cXMLState, rxml_state_alloc);
46
46
 
47
47
  /* Create one instance of the state object that is used
48
48
  to initalize and cleanup libxml. Then register it with
@@ -1,7 +1,7 @@
1
1
  /* $Id$ */
2
2
 
3
- #ifndef __RUBY_XML_STATE__
4
- #define __RUBY_XML_STATE__
3
+ #ifndef __rxml_STATE__
4
+ #define __rxml_STATE__
5
5
 
6
6
  extern VALUE cXMLState;
7
7
  extern VALUE LIBXML_STATE;
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_xinclude.c 566 2008-11-18 06:53:36Z cfis $ */
1
+ /* $Id: rxml_xinclude.c 566 2008-11-18 06:53:36Z cfis $ */
2
2
 
3
3
  #include "ruby_libxml.h"
4
4
  #include "ruby_xml_xinclude.h"
@@ -1,9 +1,9 @@
1
- /* $Id: ruby_xml_xinclude.h 39 2006-02-21 20:40:16Z roscopeco $ */
1
+ /* $Id: ruby_xml_xinclude.h 612 2008-11-21 08:01:29Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
5
- #ifndef __RUBY_XML_XINCLUDE__
6
- #define __RUBY_XML_XINCLUDE__
5
+ #ifndef __rxml_XINCLUDE__
6
+ #define __rxml_XINCLUDE__
7
7
 
8
8
  extern VALUE cXMLXInclude;
9
9
  extern VALUE eXMLXIncludeError;
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_xpath.c 566 2008-11-18 06:53:36Z cfis $ */
1
+ /* $Id: rxml_xpath.c 566 2008-11-18 06:53:36Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -1,21 +1,12 @@
1
- /* $Id: ruby_xml_xpath.h 528 2008-11-15 23:43:48Z cfis $ */
1
+ /* $Id: ruby_xml_xpath.h 614 2008-11-22 08:04:39Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
5
- #ifndef __RUBY_XML_XPATH__
6
- #define __RUBY_XML_XPATH__
5
+ #ifndef __rxml_XPATH__
6
+ #define __rxml_XPATH__
7
7
 
8
8
  extern VALUE mXPath;
9
9
 
10
- typedef struct ruby_xml_xpath {
11
- VALUE xd;
12
- VALUE ctxt;
13
- xmlXPathObjectPtr xpop;
14
- } ruby_xml_xpath;
15
-
16
- void ruby_xml_xpath_free(ruby_xml_xpath *rxxp);
17
- VALUE ruby_xml_xpath_find(VALUE class, VALUE anode, VALUE xpath_expr, VALUE nslist);
18
-
19
10
  void ruby_init_xml_xpath(void);
20
11
 
21
12
  #endif
@@ -1,294 +1,293 @@
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
- }
1
+ /* $Id: ruby_xml_xpath_context.c 612 2008-11-21 08:01: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
+ static void
28
+ rxml_xpath_context_free(xmlXPathContextPtr ctxt) {
29
+ xmlXPathFreeContext(ctxt);
30
+ }
31
+
32
+
33
+ static VALUE
34
+ rxml_xpath_context_alloc(VALUE klass) {
35
+ return Data_Wrap_Struct(cXMLXPathContext,
36
+ NULL,
37
+ rxml_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
+ static VALUE
53
+ rxml_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
+ static VALUE
95
+ rxml_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
+ static VALUE
121
+ rxml_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
+ rxml_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
+ rxml_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
+ static VALUE
187
+ rxml_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
+ rxml_xpath_context_register_namespace(self, rprefix, ruri);
206
+ break;
207
+ case T_ARRAY:
208
+ for (i = 0; i < RARRAY(nslist)->len; i++) {
209
+ rxml_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
+ static VALUE
231
+ rxml_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
+ static VALUE
248
+ rxml_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
+ rxml_raise(xerror);
275
+ }
276
+
277
+ result = rxml_xpath_object_wrap(xobject);
278
+ rb_iv_set(result, "@context", self);
279
+ return result;
280
+ }
281
+
282
+ void
283
+ ruby_init_xml_xpath_context(void) {
284
+ cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
285
+ rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
286
+ rb_define_attr(cXMLXPathContext, "doc", 1, 0);
287
+ rb_define_method(cXMLXPathContext, "initialize", rxml_xpath_context_initialize, 1);
288
+ rb_define_method(cXMLXPathContext, "register_namespaces", rxml_xpath_context_register_namespaces, 1);
289
+ rb_define_method(cXMLXPathContext, "register_namespaces_from_node", rxml_xpath_context_register_namespaces_from_node, 1);
290
+ rb_define_method(cXMLXPathContext, "register_namespace", rxml_xpath_context_register_namespace, 2);
291
+ rb_define_method(cXMLXPathContext, "node=", rxml_xpath_context_node_set, 1);
292
+ rb_define_method(cXMLXPathContext, "find", rxml_xpath_context_find, 1);
293
+ }