libxml-ruby 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/CHANGES +41 -1
  2. data/LICENSE +3 -4
  3. data/README +37 -24
  4. data/Rakefile +2 -2
  5. data/ext/libxml/extconf.rb +31 -12
  6. data/ext/libxml/libxml.c +56 -858
  7. data/ext/libxml/ruby_libxml.h +93 -96
  8. data/ext/libxml/ruby_xml.c +855 -0
  9. data/ext/libxml/ruby_xml.h +9 -0
  10. data/ext/libxml/ruby_xml_attr.c +3 -9
  11. data/ext/libxml/ruby_xml_attr.h +2 -2
  12. data/ext/libxml/ruby_xml_attr_decl.c +2 -8
  13. data/ext/libxml/ruby_xml_attr_decl.h +1 -1
  14. data/ext/libxml/ruby_xml_attributes.c +6 -8
  15. data/ext/libxml/ruby_xml_attributes.h +1 -1
  16. data/ext/libxml/ruby_xml_document.c +915 -895
  17. data/ext/libxml/ruby_xml_document.h +2 -2
  18. data/ext/libxml/ruby_xml_dtd.c +257 -136
  19. data/ext/libxml/ruby_xml_dtd.h +1 -1
  20. data/ext/libxml/ruby_xml_encoding.c +55 -37
  21. data/ext/libxml/ruby_xml_encoding.h +1 -1
  22. data/ext/libxml/ruby_xml_error.c +526 -1058
  23. data/ext/libxml/ruby_xml_error.h +1 -1
  24. data/ext/libxml/ruby_xml_html_parser.c +2 -8
  25. data/ext/libxml/ruby_xml_html_parser.h +2 -2
  26. data/ext/libxml/ruby_xml_html_parser_context.c +175 -145
  27. data/ext/libxml/ruby_xml_html_parser_context.h +1 -1
  28. data/ext/libxml/ruby_xml_html_parser_options.c +12 -20
  29. data/ext/libxml/ruby_xml_html_parser_options.h +1 -1
  30. data/ext/libxml/ruby_xml_input_cbg.c +2 -8
  31. data/ext/libxml/ruby_xml_input_cbg.h +1 -1
  32. data/ext/libxml/ruby_xml_namespace.c +2 -8
  33. data/ext/libxml/ruby_xml_namespace.h +2 -2
  34. data/ext/libxml/ruby_xml_namespaces.c +1 -9
  35. data/ext/libxml/ruby_xml_namespaces.h +1 -1
  36. data/ext/libxml/ruby_xml_node.c +182 -121
  37. data/ext/libxml/ruby_xml_node.h +2 -2
  38. data/ext/libxml/ruby_xml_parser.c +2 -8
  39. data/ext/libxml/ruby_xml_parser.h +2 -2
  40. data/ext/libxml/ruby_xml_parser_context.c +952 -901
  41. data/ext/libxml/ruby_xml_parser_context.h +2 -2
  42. data/ext/libxml/ruby_xml_parser_options.c +2 -9
  43. data/ext/libxml/ruby_xml_parser_options.h +1 -1
  44. data/ext/libxml/ruby_xml_reader.c +1002 -993
  45. data/ext/libxml/ruby_xml_reader.h +1 -1
  46. data/ext/libxml/ruby_xml_relaxng.c +1 -7
  47. data/ext/libxml/ruby_xml_relaxng.h +1 -1
  48. data/ext/libxml/ruby_xml_sax2_handler.c +2 -2
  49. data/ext/libxml/ruby_xml_sax2_handler.h +1 -1
  50. data/ext/libxml/ruby_xml_sax_parser.c +2 -8
  51. data/ext/libxml/ruby_xml_sax_parser.h +2 -2
  52. data/ext/libxml/ruby_xml_schema.c +1 -7
  53. data/ext/libxml/ruby_xml_schema.h +1 -1
  54. data/ext/libxml/{version.h → ruby_xml_version.h} +2 -2
  55. data/ext/libxml/ruby_xml_xinclude.c +2 -8
  56. data/ext/libxml/ruby_xml_xinclude.h +2 -2
  57. data/ext/libxml/ruby_xml_xpath.c +17 -18
  58. data/ext/libxml/ruby_xml_xpath.h +2 -2
  59. data/ext/libxml/ruby_xml_xpath_context.c +387 -389
  60. data/ext/libxml/ruby_xml_xpath_context.h +2 -2
  61. data/ext/libxml/ruby_xml_xpath_expression.c +18 -8
  62. data/ext/libxml/ruby_xml_xpath_expression.h +1 -1
  63. data/ext/libxml/ruby_xml_xpath_object.c +19 -8
  64. data/ext/libxml/ruby_xml_xpath_object.h +1 -1
  65. data/ext/libxml/ruby_xml_xpointer.c +2 -8
  66. data/ext/libxml/ruby_xml_xpointer.h +2 -2
  67. data/ext/vc/libxml_ruby.sln +7 -1
  68. data/lib/libxml.rb +1 -12
  69. data/lib/libxml/attr.rb +0 -3
  70. data/lib/libxml/attr_decl.rb +0 -3
  71. data/lib/libxml/attributes.rb +0 -3
  72. data/lib/libxml/document.rb +31 -5
  73. data/lib/libxml/error.rb +8 -4
  74. data/lib/libxml/properties.rb +0 -5
  75. data/lib/libxml/sax_callbacks.rb +30 -19
  76. data/lib/libxml/tree.rb +0 -1
  77. data/lib/libxml/xpath_object.rb +0 -13
  78. data/test/model/definition.dtd +8 -0
  79. data/test/tc_attributes.rb +4 -1
  80. data/test/tc_document.rb +16 -0
  81. data/test/tc_dtd.rb +30 -2
  82. data/test/tc_html_parser.rb +55 -10
  83. data/test/tc_node.rb +67 -1
  84. data/test/tc_node_edit.rb +26 -6
  85. data/test/tc_node_text.rb +41 -23
  86. data/test/tc_parser.rb +50 -0
  87. data/test/tc_reader.rb +15 -0
  88. data/test/tc_relaxng.rb +1 -1
  89. data/test/tc_sax_parser.rb +37 -5
  90. data/test/tc_schema.rb +1 -1
  91. data/test/tc_xpath.rb +1 -0
  92. data/test/tc_xpath_expression.rb +4 -2
  93. metadata +6 -6
  94. data/ext/libxml/ruby_xml_state.c +0 -51
  95. data/ext/libxml/ruby_xml_state.h +0 -11
  96. data/ext/vc/libxml_ruby.vcproj +0 -460
@@ -6,7 +6,7 @@
6
6
 
7
7
  extern VALUE cXMLReader;
8
8
 
9
- void ruby_init_xml_reader(void);
9
+ void rxml_init_reader(void);
10
10
 
11
11
  /* Exported to be used by XML::Document#reader */
12
12
  VALUE rxml_reader_new_walker(VALUE self, VALUE doc);
@@ -32,12 +32,6 @@
32
32
 
33
33
  VALUE cXMLRelaxNG;
34
34
 
35
- // Rdoc needs to know
36
- #ifdef RDOC_NEVER_DEFINED
37
- mLibXML = rb_define_module("LibXML");
38
- mXML = rb_define_module_under(mLibXML, "XML");
39
- #endif
40
-
41
35
  static void rxml_relaxng_free(xmlRelaxNGPtr xrelaxng)
42
36
  {
43
37
  xmlRelaxNGFree(xrelaxng);
@@ -105,7 +99,7 @@ static VALUE rxml_relaxng_init_from_string(VALUE self, VALUE relaxng_str)
105
99
  return Data_Wrap_Struct(cXMLRelaxNG, NULL, rxml_relaxng_free, xrelaxng);
106
100
  }
107
101
 
108
- void ruby_init_xml_relaxng(void)
102
+ void rxml_init_relaxng(void)
109
103
  {
110
104
  cXMLRelaxNG = rb_define_class_under(mXML, "RelaxNG", rb_cObject);
111
105
  rb_define_singleton_method(cXMLRelaxNG, "new", rxml_relaxng_init_from_uri, 1);
@@ -5,6 +5,6 @@
5
5
 
6
6
  extern VALUE cXMLRelaxNG;
7
7
 
8
- void ruby_init_xml_relaxng(void);
8
+ void rxml_init_relaxng(void);
9
9
  #endif
10
10
 
@@ -222,7 +222,7 @@ static void start_element_ns_callback(void *ctx,
222
222
  {
223
223
  VALUE nsPrefix = xnamespaces[i+0] ? rb_str_new2(xnamespaces[i+0]) : Qnil;
224
224
  VALUE nsURI = xnamespaces[i+1] ? rb_str_new2(xnamespaces[i+1]) : Qnil;
225
- rb_hash_aset(attributes, nsPrefix, nsURI);
225
+ rb_hash_aset(namespaces, nsPrefix, nsURI);
226
226
  }
227
227
  }
228
228
 
@@ -298,7 +298,7 @@ xmlSAXHandler rxml_sax_handler = {
298
298
  (xmlStructuredErrorFunc) structured_error_callback
299
299
  };
300
300
 
301
- void ruby_init_xml_sax2_handler(void)
301
+ void rxml_init_sax2_handler(void)
302
302
  {
303
303
 
304
304
  /* SaxCallbacks */
@@ -7,6 +7,6 @@
7
7
 
8
8
  extern xmlSAXHandler rxml_sax_handler;
9
9
 
10
- void ruby_init_xml_sax2_handler(void);
10
+ void rxml_init_sax2_handler(void);
11
11
 
12
12
  #endif
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_sax_parser.c 740 2009-01-23 04:03:11Z cfis $ */
1
+ /* $Id: ruby_xml_sax_parser.c 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -121,13 +121,7 @@ static VALUE rxml_sax_parser_parse(VALUE self)
121
121
  return Qtrue;
122
122
  }
123
123
 
124
- // Rdoc needs to know
125
- #ifdef RDOC_NEVER_DEFINED
126
- mLibXML = rb_define_module("LibXML");
127
- mXML = rb_define_module_under(mLibXML, "XML");
128
- #endif
129
-
130
- void ruby_init_xml_sax_parser(void)
124
+ void rxml_init_sax_parser(void)
131
125
  {
132
126
  /* SaxParser */
133
127
  cXMLSaxParser = rb_define_class_under(mXML, "SaxParser", rb_cObject);
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_sax_parser.h 666 2008-12-07 00:16:50Z cfis $ */
1
+ /* $Id: ruby_xml_sax_parser.h 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -7,6 +7,6 @@
7
7
 
8
8
  extern VALUE cXMLSaxParser;
9
9
 
10
- void ruby_init_xml_sax_parser(void);
10
+ void rxml_init_sax_parser(void);
11
11
 
12
12
  #endif
@@ -32,12 +32,6 @@
32
32
 
33
33
  VALUE cXMLSchema;
34
34
 
35
- // Rdoc needs to know
36
- #ifdef RDOC_NEVER_DEFINED
37
- mLibXML = rb_define_module("LibXML");
38
- mXML = rb_define_module_under(mLibXML, "XML");
39
- #endif
40
-
41
35
  static void rxml_schema_free(xmlSchemaPtr xschema)
42
36
  {
43
37
  xmlSchemaFree(xschema);
@@ -153,7 +147,7 @@ static VALUE rxml_schema_init_from_string(VALUE self, VALUE schema_str)
153
147
  } else if (!strcmp(method, "validate_schema_buffer")) {
154
148
  */
155
149
 
156
- void ruby_init_xml_schema(void)
150
+ void rxml_init_schema(void)
157
151
  {
158
152
  cXMLSchema = rb_define_class_under(mXML, "Schema", rb_cObject);
159
153
  rb_define_singleton_method(cXMLSchema, "new", rxml_schema_init_from_uri, 1);
@@ -6,6 +6,6 @@
6
6
 
7
7
  extern VALUE cXMLSchema;
8
8
 
9
- void ruby_init_xml_schema(void);
9
+ void rxml_init_schema(void);
10
10
  #endif
11
11
 
@@ -1,9 +1,9 @@
1
1
  /* Don't nuke this block! It is used for automatically updating the
2
2
  * versions below. VERSION = string formatting, VERNUM = numbered
3
3
  * version for inline testing: increment both or none at all.*/
4
- #define RUBY_LIBXML_VERSION "0.9.8"
4
+ #define RUBY_LIBXML_VERSION "0.9.9"
5
5
  #define RUBY_LIBXML_VERNUM 0
6
6
  #define RUBY_LIBXML_VER_MAJ 0
7
7
  #define RUBY_LIBXML_VER_MIN 9
8
- #define RUBY_LIBXML_VER_MIC 8
8
+ #define RUBY_LIBXML_VER_MIC 9
9
9
  #define RUBY_LIBXML_VER_PATCH 0
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_xinclude.c 650 2008-11-30 03:40:22Z cfis $ */
1
+ /* $Id: ruby_xml_xinclude.c 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  #include "ruby_libxml.h"
4
4
  #include "ruby_xml_xinclude.h"
@@ -12,13 +12,7 @@ VALUE cXMLXInclude;
12
12
  * XInclude fuctionality.
13
13
  */
14
14
 
15
- // Rdoc needs to know
16
- #ifdef RDOC_NEVER_DEFINED
17
- mLibXML = rb_define_module("LibXML");
18
- mXML = rb_define_module_under(mLibXML, "XML");
19
- #endif
20
-
21
- void ruby_init_xml_xinclude(void)
15
+ void rxml_init_xinclude(void)
22
16
  {
23
17
  cXMLXInclude = rb_define_class_under(mXML, "XInclude", rb_cObject);
24
18
  }
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_xinclude.h 666 2008-12-07 00:16:50Z cfis $ */
1
+ /* $Id: ruby_xml_xinclude.h 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -8,6 +8,6 @@
8
8
  extern VALUE cXMLXInclude;
9
9
  extern VALUE eXMLXIncludeError;
10
10
 
11
- void ruby_init_xml_xinclude(void);
11
+ void rxml_init_xinclude(void);
12
12
 
13
13
  #endif
@@ -1,10 +1,4 @@
1
- /* $Id: ruby_xml_xpath.c 666 2008-12-07 00:16:50Z cfis $ */
2
-
3
- /* Please see the LICENSE file for copyright and distribution information */
4
-
5
- #include "ruby_libxml.h"
6
- #include "ruby_xml_xpath.h"
7
- #include "ruby_xml_xpath_context.h"
1
+ /* $Id: ruby_xml_xpath.c 759 2009-01-26 00:15:49Z cfis $ */
8
2
 
9
3
  /*
10
4
  * Document-class: LibXML::XML::XPath
@@ -78,31 +72,36 @@
78
72
  * # Here is an example showing a complex namespace aware
79
73
  * # xpath expression.
80
74
  * doc.find('/soap:Envelope/soap:Body/ns0:getManufacturerNamesResponse/ns0:IDAndNameList/ns1:IdAndName',
81
- ['ns0:http://services.somewhere.com', 'ns1:http://domain.somewhere.com'])
82
- */
75
+ * ['ns0:http://services.somewhere.com', 'ns1:http://domain.somewhere.com'])
76
+ */
83
77
 
84
- VALUE mXPath;
85
78
 
86
- // Rdoc needs to know
87
- #ifdef RDOC_NEVER_DEFINED
88
- mLibXML = rb_define_module("LibXML");
89
- mXML = rb_define_module_under(mLibXML, "XML");
90
- #endif
79
+ #include "ruby_libxml.h"
80
+
81
+ VALUE mXPath;
91
82
 
92
- void ruby_init_xml_xpath(void)
83
+ void rxml_init_xpath(void)
93
84
  {
94
85
  mXPath = rb_define_module_under(mXML, "XPath");
95
86
 
87
+ /* 0: Undefined value. */
96
88
  rb_define_const(mXPath, "UNDEFINED", INT2NUM(XPATH_UNDEFINED));
89
+ /* 1: A nodeset, will be wrapped by XPath Object. */
97
90
  rb_define_const(mXPath, "NODESET", INT2NUM(XPATH_NODESET));
91
+ /* 2: A boolean value. */
98
92
  rb_define_const(mXPath, "BOOLEAN", INT2NUM(XPATH_BOOLEAN));
93
+ /* 3: A numeric value. */
99
94
  rb_define_const(mXPath, "NUMBER", INT2NUM(XPATH_NUMBER));
95
+ /* 4: A string value. */
100
96
  rb_define_const(mXPath, "STRING", INT2NUM(XPATH_STRING));
97
+ /* 5: An xpointer point */
101
98
  rb_define_const(mXPath, "POINT", INT2NUM(XPATH_POINT));
99
+ /* 6: An xpointer range */
102
100
  rb_define_const(mXPath, "RANGE", INT2NUM(XPATH_RANGE));
101
+ /* 7: An xpointer location set */
103
102
  rb_define_const(mXPath, "LOCATIONSET", INT2NUM(XPATH_LOCATIONSET));
103
+ /* 8: XPath user type */
104
104
  rb_define_const(mXPath, "USERS", INT2NUM(XPATH_USERS));
105
+ /* 9: An XSLT value tree, non modifiable */
105
106
  rb_define_const(mXPath, "XSLT_TREE", INT2NUM(XPATH_XSLT_TREE));
106
-
107
- ruby_init_xml_xpath_object();
108
107
  }
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_xpath.h 666 2008-12-07 00:16:50Z cfis $ */
1
+ /* $Id: ruby_xml_xpath.h 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -7,6 +7,6 @@
7
7
 
8
8
  extern VALUE mXPath;
9
9
 
10
- void ruby_init_xml_xpath(void);
10
+ void rxml_init_xpath(void);
11
11
 
12
12
  #endif
@@ -1,389 +1,387 @@
1
- /* $Id: ruby_xml_xpath_context.c 739 2009-01-23 03:42:09Z 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
- * Document-class: LibXML::XML::XPath::Context
12
- *
13
- * The XML::XPath::Context class is used to evaluate XPath
14
- * expressions. Generally, you should not directly use this class,
15
- * but instead use the XML::Document#find and XML::Node#find methods.
16
- *
17
- * doc = XML::Document.string('<header>content</header>')
18
- * context = XPath::Context.new(doc)
19
- * context.node = doc.root
20
- * context.register_namespaces_from_node(doc.root)
21
- * nodes = context.find('/header')
22
- */
23
-
24
- VALUE cXMLXPathContext;
25
-
26
- static ID DOC_ATTRIBUTE;
27
-
28
- static void rxml_xpath_context_free(xmlXPathContextPtr ctxt)
29
- {
30
- xmlXPathFreeContext(ctxt);
31
- }
32
-
33
- static VALUE rxml_xpath_context_alloc(VALUE klass)
34
- {
35
- return Data_Wrap_Struct(cXMLXPathContext, NULL, rxml_xpath_context_free, NULL);
36
- }
37
-
38
- /* call-seq:
39
- * XPath::Context.new(node) -> XPath::Context
40
- *
41
- * Creates a new XPath context for the specified document. The
42
- * context can then be used to evaluate an XPath expression.
43
- *
44
- * doc = XML::Document.string('<header><first>hi</first></header>')
45
- * context = XPath::Context.new(doc)
46
- * nodes = XPath::Object.new('//first', context)
47
- * nodes.length == 1
48
- */
49
- static VALUE rxml_xpath_context_initialize(VALUE self, VALUE node)
50
- {
51
- xmlDocPtr xdoc;
52
- VALUE document;
53
-
54
- if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
55
- {
56
- document = rb_funcall(node, rb_intern("doc"), 0);
57
- if (NIL_P(document))
58
- rb_raise(rb_eTypeError, "Supplied node must belong to a document.");
59
- }
60
- else if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
61
- {
62
- document = node;
63
- }
64
- else
65
- {
66
- rb_raise(rb_eTypeError, "Supplied argument must be a document or node.");
67
- }
68
-
69
- Data_Get_Struct(document, xmlDoc, xdoc);
70
- DATA_PTR(self) = xmlXPathNewContext(xdoc);
71
-
72
- /* Save the doc as an attribute, this will expose it to Ruby's GC. */
73
- rb_ivar_set(self, DOC_ATTRIBUTE, document);
74
-
75
- return self;
76
- }
77
-
78
- /*
79
- * call-seq:
80
- * context.register_namespace(prefix, uri) -> (true|false)
81
- *
82
- * Register the specified namespace URI with the specified prefix
83
- * in this context.
84
-
85
- * context.register_namespace('xi', 'http://www.w3.org/2001/XInclude')
86
- */
87
- static VALUE rxml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri)
88
- {
89
- xmlXPathContextPtr ctxt;
90
- Data_Get_Struct(self, xmlXPathContext, ctxt);
91
-
92
- /* Prefix could be a symbol. */
93
- prefix = rb_obj_as_string(prefix);
94
-
95
- if (xmlXPathRegisterNs(ctxt, (xmlChar*) StringValuePtr(prefix),
96
- (xmlChar*) StringValuePtr(uri)) == 0)
97
- {
98
- return (Qtrue);
99
- }
100
- else
101
- {
102
- /* Should raise an exception, IMHO (whose?, why shouldnt it? -danj)*/
103
- rb_warning("register namespace failed");
104
- return (Qfalse);
105
- }
106
- }
107
-
108
- /* call-seq:
109
- * context.register_namespaces_from_node(node) -> self
110
- *
111
- * Helper method to read in namespaces defined on a node.
112
- *
113
- * doc = XML::Document.string('<header><first>hi</first></header>')
114
- * context = XPath::Context.new(doc)
115
- * context.register_namespaces_from_node(doc.root)
116
- */
117
- static VALUE rxml_xpath_context_register_namespaces_from_node(VALUE self,
118
- VALUE node)
119
- {
120
- xmlXPathContextPtr xctxt;
121
- xmlNodePtr xnode;
122
- xmlNsPtr *xnsArr;
123
-
124
- Data_Get_Struct(self, xmlXPathContext, xctxt);
125
-
126
- if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
127
- {
128
- xmlDocPtr xdoc;
129
- Data_Get_Struct(node, xmlDoc, xdoc);
130
- xnode = xmlDocGetRootElement(xdoc);
131
- }
132
- else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
133
- {
134
- Data_Get_Struct(node, xmlNode, xnode);
135
- }
136
- else
137
- {
138
- rb_raise(rb_eTypeError, "The first argument must be a document or node.");
139
- }
140
-
141
- xnsArr = xmlGetNsList(xnode->doc, xnode);
142
-
143
- if (xnsArr)
144
- {
145
- xmlNsPtr xns = *xnsArr;
146
-
147
- while (xns)
148
- {
149
- /* If there is no prefix, then this is the default namespace.
150
- Skip it for now. */
151
- if (xns->prefix)
152
- {
153
- VALUE prefix = rb_str_new2((const char*)xns->prefix);
154
- VALUE uri = rb_str_new2((const char*)xns->href);
155
- rxml_xpath_context_register_namespace(self, prefix, uri);
156
- }
157
- xns = xns->next;
158
- }
159
- xmlFree(xnsArr);
160
- }
161
-
162
- return self;
163
- }
164
-
165
- static int iterate_ns_hash(st_data_t prefix, st_data_t uri, st_data_t self)
166
- {
167
- rxml_xpath_context_register_namespace(self, prefix, uri);
168
- return ST_CONTINUE;
169
- }
170
-
171
- /*
172
- * call-seq:
173
- * context.register_namespaces(["prefix:uri"]) -> self
174
- *
175
- * Register the specified namespaces in this context. There are
176
- * three different forms that libxml accepts. These include
177
- * a string, an array of strings, or a hash table:
178
- *
179
- * context.register_namespaces('xi:http://www.w3.org/2001/XInclude')
180
- * context.register_namespaces(['xlink:http://www.w3.org/1999/xlink',
181
- * 'xi:http://www.w3.org/2001/XInclude')
182
- * context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink',
183
- * 'xi' => 'http://www.w3.org/2001/XInclude')
184
- */
185
- static VALUE rxml_xpath_context_register_namespaces(VALUE self, VALUE nslist)
186
- {
187
- char *cp;
188
- long i;
189
- VALUE rprefix, ruri;
190
-
191
- /* Need to loop through the 2nd argument and iterate through the
192
- * list of namespaces that we want to allow */
193
- switch (TYPE(nslist))
194
- {
195
- case T_STRING:
196
- cp = strchr(StringValuePtr(nslist), (int) ':');
197
- if (cp == NULL)
198
- {
199
- rprefix = nslist;
200
- ruri = Qnil;
201
- }
202
- else
203
- {
204
- rprefix = rb_str_new(StringValuePtr(nslist), (int) ((long) cp
205
- - (long) StringValuePtr(nslist)));
206
- ruri = rb_str_new2(&cp[1]);
207
- }
208
- /* Should test the results of this */
209
- rxml_xpath_context_register_namespace(self, rprefix, ruri);
210
- break;
211
- case T_ARRAY:
212
- for (i = 0; i < RARRAY_LEN(nslist); i++)
213
- {
214
- rxml_xpath_context_register_namespaces(self, RARRAY_PTR(nslist)[i]);
215
- }
216
- break;
217
- case T_HASH:
218
- st_foreach(RHASH_TBL(nslist), iterate_ns_hash, self);
219
- break;
220
- default:
221
- rb_raise(
222
- rb_eArgError,
223
- "Invalid argument type, only accept string, array of strings, or an array of arrays");
224
- }
225
- return self;
226
- }
227
-
228
- /*
229
- * call-seq:
230
- * context.node = node
231
- *
232
- * Set the current node used by the XPath engine
233
-
234
- * doc = XML::Document.string('<header><first>hi</first></header>')
235
- * context.node = doc.root.first
236
- */
237
- static VALUE rxml_xpath_context_node_set(VALUE self, VALUE node)
238
- {
239
- xmlXPathContextPtr xctxt;
240
- xmlNodePtr xnode;
241
-
242
- Data_Get_Struct(self, xmlXPathContext, xctxt);
243
- Data_Get_Struct(node, xmlNode, xnode);
244
- xctxt->node = xnode;
245
- return node;
246
- }
247
-
248
- /*
249
- * call-seq:
250
- * context.find("xpath") -> true|false|number|string|XML::XPath::Object
251
- *
252
- * Executes the provided xpath function. The result depends on the execution
253
- * of the xpath statement. It may be true, false, a number, a string or
254
- * a node set.
255
- */
256
- static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
257
- {
258
- xmlXPathContextPtr xctxt;
259
- xmlXPathObjectPtr xobject;
260
- xmlXPathCompExprPtr xcompexpr;
261
- VALUE result;
262
-
263
- Data_Get_Struct(self, xmlXPathContext, xctxt);
264
-
265
- if (TYPE(xpath_expr) == T_STRING)
266
- {
267
- VALUE expression = rb_check_string_type(xpath_expr);
268
- xobject = xmlXPathEval((xmlChar*) StringValueCStr(expression), xctxt);
269
- }
270
- else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression))
271
- {
272
- Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr);
273
- xobject = xmlXPathCompiledEval(xcompexpr, xctxt);
274
- }
275
- else
276
- {
277
- rb_raise(rb_eTypeError,
278
- "Argument should be an intance of a String or XPath::Expression");
279
- }
280
-
281
- if (xobject == NULL)
282
- {
283
- /* xmlLastError is different than xctxt->lastError. Use
284
- xmlLastError since it has the message set while xctxt->lastError
285
- does not. */
286
- xmlErrorPtr xerror = xmlGetLastError();
287
- rxml_raise(xerror);
288
- }
289
-
290
- switch (xobject->type)
291
- {
292
- case XPATH_NODESET:
293
- result = rxml_xpath_object_wrap(xctxt->doc, xobject);
294
- break;
295
- case XPATH_BOOLEAN:
296
- result = (xobject->boolval != 0) ? Qtrue : Qfalse;
297
- xmlXPathFreeObject(xobject);
298
- break;
299
- case XPATH_NUMBER:
300
- result = rb_float_new(xobject->floatval);
301
- xmlXPathFreeObject(xobject);
302
- break;
303
- case XPATH_STRING:
304
- result = rb_str_new2((const char*)xobject->stringval);
305
- xmlXPathFreeObject(xobject);
306
- break;
307
- default:
308
- result = Qnil;
309
- xmlXPathFreeObject(xobject);
310
- }
311
- return result;
312
- }
313
-
314
- #if LIBXML_VERSION >= 20626
315
- /*
316
- * call-seq:
317
- * context.enable_cache(size = nil)
318
- *
319
- * Enables an XPath::Context's built-in cache. If the cache is
320
- * enabled then XPath objects will be cached internally for reuse.
321
- * The size parameter controls sets the maximum number of XPath objects
322
- * that will be cached per XPath object type (node-set, string, number,
323
- * boolean, and misc objects). Set size to nil to use the default
324
- * cache size of 100.
325
- */
326
- static VALUE
327
- rxml_xpath_context_enable_cache(int argc, VALUE *argv, VALUE self)
328
- {
329
- xmlXPathContextPtr xctxt;
330
- VALUE size;
331
- int value = -1;
332
-
333
- Data_Get_Struct(self, xmlXPathContext, xctxt);
334
-
335
- if (rb_scan_args(argc, argv, "01", &size) == 1)
336
- {
337
- value = NUM2INT(size);
338
- }
339
-
340
- if (xmlXPathContextSetCache(xctxt, 1, value, 0) == -1)
341
- rxml_raise(&xmlLastError);
342
-
343
- return self;
344
- }
345
-
346
- /*
347
- * call-seq:
348
- * context.disable_cache
349
- *
350
- * Disables an XPath::Context's built-in cache.
351
- */
352
- static VALUE
353
- rxml_xpath_context_disable_cache(VALUE self)
354
- {
355
- xmlXPathContextPtr xctxt;
356
- Data_Get_Struct(self, xmlXPathContext, xctxt);
357
-
358
- if (xmlXPathContextSetCache(xctxt, 0, 0, 0) == -1)
359
- rxml_raise(&xmlLastError);
360
-
361
- return self;
362
- }
363
- #endif
364
-
365
-
366
- // Rdoc needs to know
367
- #ifdef RDOC_NEVER_DEFINED
368
- mLibXML = rb_define_module("LibXML");
369
- mXPath = rb_define_module_under(mLibXML, "XPath");
370
- #endif
371
-
372
- void ruby_init_xml_xpath_context(void)
373
- {
374
- DOC_ATTRIBUTE = rb_intern("@doc");
375
-
376
- cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
377
- rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
378
- rb_define_attr(cXMLXPathContext, "doc", 1, 0);
379
- rb_define_method(cXMLXPathContext, "initialize", rxml_xpath_context_initialize, 1);
380
- rb_define_method(cXMLXPathContext, "register_namespaces", rxml_xpath_context_register_namespaces, 1);
381
- rb_define_method(cXMLXPathContext, "register_namespaces_from_node", rxml_xpath_context_register_namespaces_from_node, 1);
382
- rb_define_method(cXMLXPathContext, "register_namespace", rxml_xpath_context_register_namespace, 2);
383
- rb_define_method(cXMLXPathContext, "node=", rxml_xpath_context_node_set, 1);
384
- rb_define_method(cXMLXPathContext, "find", rxml_xpath_context_find, 1);
385
- #if LIBXML_VERSION >= 20626
386
- rb_define_method(cXMLXPathContext, "enable_cache", rxml_xpath_context_enable_cache, -1);
387
- rb_define_method(cXMLXPathContext, "disable_cache", rxml_xpath_context_disable_cache, 0);
388
- #endif
389
- }
1
+ /* $Id: ruby_xml_xpath_context.c 799 2009-03-02 01:45:24Z 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
+
9
+ #if RUBY_ST_H
10
+ #include <ruby/st.h>
11
+ #else
12
+ #include <st.h>
13
+ #endif
14
+
15
+ /*
16
+ * Document-class: LibXML::XML::XPath::Context
17
+ *
18
+ * The XML::XPath::Context class is used to evaluate XPath
19
+ * expressions. Generally, you should not directly use this class,
20
+ * but instead use the XML::Document#find and XML::Node#find methods.
21
+ *
22
+ * doc = XML::Document.string('<header>content</header>')
23
+ * context = XPath::Context.new(doc)
24
+ * context.node = doc.root
25
+ * context.register_namespaces_from_node(doc.root)
26
+ * nodes = context.find('/header')
27
+ */
28
+
29
+ VALUE cXMLXPathContext;
30
+
31
+ static ID DOC_ATTRIBUTE;
32
+
33
+ static void rxml_xpath_context_free(xmlXPathContextPtr ctxt)
34
+ {
35
+ xmlXPathFreeContext(ctxt);
36
+ }
37
+
38
+ static VALUE rxml_xpath_context_alloc(VALUE klass)
39
+ {
40
+ return Data_Wrap_Struct(cXMLXPathContext, NULL, rxml_xpath_context_free, NULL);
41
+ }
42
+
43
+ /* call-seq:
44
+ * XPath::Context.new(node) -> XPath::Context
45
+ *
46
+ * Creates a new XPath context for the specified document. The
47
+ * context can then be used to evaluate an XPath expression.
48
+ *
49
+ * doc = XML::Document.string('<header><first>hi</first></header>')
50
+ * context = XPath::Context.new(doc)
51
+ * nodes = XPath::Object.new('//first', context)
52
+ * nodes.length == 1
53
+ */
54
+ static VALUE rxml_xpath_context_initialize(VALUE self, VALUE node)
55
+ {
56
+ xmlDocPtr xdoc;
57
+ VALUE document;
58
+
59
+ if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
60
+ {
61
+ document = rb_funcall(node, rb_intern("doc"), 0);
62
+ if (NIL_P(document))
63
+ rb_raise(rb_eTypeError, "Supplied node must belong to a document.");
64
+ }
65
+ else if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
66
+ {
67
+ document = node;
68
+ }
69
+ else
70
+ {
71
+ rb_raise(rb_eTypeError, "Supplied argument must be a document or node.");
72
+ }
73
+
74
+ Data_Get_Struct(document, xmlDoc, xdoc);
75
+ DATA_PTR(self) = xmlXPathNewContext(xdoc);
76
+
77
+ /* Save the doc as an attribute, this will expose it to Ruby's GC. */
78
+ rb_ivar_set(self, DOC_ATTRIBUTE, document);
79
+
80
+ return self;
81
+ }
82
+
83
+ /*
84
+ * call-seq:
85
+ * context.register_namespace(prefix, uri) -> (true|false)
86
+ *
87
+ * Register the specified namespace URI with the specified prefix
88
+ * in this context.
89
+
90
+ * context.register_namespace('xi', 'http://www.w3.org/2001/XInclude')
91
+ */
92
+ static VALUE rxml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri)
93
+ {
94
+ xmlXPathContextPtr ctxt;
95
+ Data_Get_Struct(self, xmlXPathContext, ctxt);
96
+
97
+ /* Prefix could be a symbol. */
98
+ prefix = rb_obj_as_string(prefix);
99
+
100
+ if (xmlXPathRegisterNs(ctxt, (xmlChar*) StringValuePtr(prefix),
101
+ (xmlChar*) StringValuePtr(uri)) == 0)
102
+ {
103
+ return (Qtrue);
104
+ }
105
+ else
106
+ {
107
+ /* Should raise an exception, IMHO (whose?, why shouldnt it? -danj)*/
108
+ rb_warning("register namespace failed");
109
+ return (Qfalse);
110
+ }
111
+ }
112
+
113
+ /* call-seq:
114
+ * context.register_namespaces_from_node(node) -> self
115
+ *
116
+ * Helper method to read in namespaces defined on a node.
117
+ *
118
+ * doc = XML::Document.string('<header><first>hi</first></header>')
119
+ * context = XPath::Context.new(doc)
120
+ * context.register_namespaces_from_node(doc.root)
121
+ */
122
+ static VALUE rxml_xpath_context_register_namespaces_from_node(VALUE self,
123
+ VALUE node)
124
+ {
125
+ xmlXPathContextPtr xctxt;
126
+ xmlNodePtr xnode;
127
+ xmlNsPtr *xnsArr;
128
+
129
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
130
+
131
+ if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue)
132
+ {
133
+ xmlDocPtr xdoc;
134
+ Data_Get_Struct(node, xmlDoc, xdoc);
135
+ xnode = xmlDocGetRootElement(xdoc);
136
+ }
137
+ else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue)
138
+ {
139
+ Data_Get_Struct(node, xmlNode, xnode);
140
+ }
141
+ else
142
+ {
143
+ rb_raise(rb_eTypeError, "The first argument must be a document or node.");
144
+ }
145
+
146
+ xnsArr = xmlGetNsList(xnode->doc, xnode);
147
+
148
+ if (xnsArr)
149
+ {
150
+ xmlNsPtr xns = *xnsArr;
151
+
152
+ while (xns)
153
+ {
154
+ /* If there is no prefix, then this is the default namespace.
155
+ Skip it for now. */
156
+ if (xns->prefix)
157
+ {
158
+ VALUE prefix = rb_str_new2((const char*)xns->prefix);
159
+ VALUE uri = rb_str_new2((const char*)xns->href);
160
+ rxml_xpath_context_register_namespace(self, prefix, uri);
161
+ }
162
+ xns = xns->next;
163
+ }
164
+ xmlFree(xnsArr);
165
+ }
166
+
167
+ return self;
168
+ }
169
+
170
+ static int iterate_ns_hash(st_data_t prefix, st_data_t uri, st_data_t self)
171
+ {
172
+ rxml_xpath_context_register_namespace(self, prefix, uri);
173
+ return ST_CONTINUE;
174
+ }
175
+
176
+ /*
177
+ * call-seq:
178
+ * context.register_namespaces(["prefix:uri"]) -> self
179
+ *
180
+ * Register the specified namespaces in this context. There are
181
+ * three different forms that libxml accepts. These include
182
+ * a string, an array of strings, or a hash table:
183
+ *
184
+ * context.register_namespaces('xi:http://www.w3.org/2001/XInclude')
185
+ * context.register_namespaces(['xlink:http://www.w3.org/1999/xlink',
186
+ * 'xi:http://www.w3.org/2001/XInclude')
187
+ * context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink',
188
+ * 'xi' => 'http://www.w3.org/2001/XInclude')
189
+ */
190
+ static VALUE rxml_xpath_context_register_namespaces(VALUE self, VALUE nslist)
191
+ {
192
+ char *cp;
193
+ long i;
194
+ VALUE rprefix, ruri;
195
+
196
+ /* Need to loop through the 2nd argument and iterate through the
197
+ * list of namespaces that we want to allow */
198
+ switch (TYPE(nslist))
199
+ {
200
+ case T_STRING:
201
+ cp = strchr(StringValuePtr(nslist), (int) ':');
202
+ if (cp == NULL)
203
+ {
204
+ rprefix = nslist;
205
+ ruri = Qnil;
206
+ }
207
+ else
208
+ {
209
+ rprefix = rb_str_new(StringValuePtr(nslist), (int) ((long) cp
210
+ - (long) StringValuePtr(nslist)));
211
+ ruri = rb_str_new2(&cp[1]);
212
+ }
213
+ /* Should test the results of this */
214
+ rxml_xpath_context_register_namespace(self, rprefix, ruri);
215
+ break;
216
+ case T_ARRAY:
217
+ for (i = 0; i < RARRAY_LEN(nslist); i++)
218
+ {
219
+ rxml_xpath_context_register_namespaces(self, RARRAY_PTR(nslist)[i]);
220
+ }
221
+ break;
222
+ case T_HASH:
223
+ st_foreach(RHASH_TBL(nslist), iterate_ns_hash, self);
224
+ break;
225
+ default:
226
+ rb_raise(
227
+ rb_eArgError,
228
+ "Invalid argument type, only accept string, array of strings, or an array of arrays");
229
+ }
230
+ return self;
231
+ }
232
+
233
+ /*
234
+ * call-seq:
235
+ * context.node = node
236
+ *
237
+ * Set the current node used by the XPath engine
238
+
239
+ * doc = XML::Document.string('<header><first>hi</first></header>')
240
+ * context.node = doc.root.first
241
+ */
242
+ static VALUE rxml_xpath_context_node_set(VALUE self, VALUE node)
243
+ {
244
+ xmlXPathContextPtr xctxt;
245
+ xmlNodePtr xnode;
246
+
247
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
248
+ Data_Get_Struct(node, xmlNode, xnode);
249
+ xctxt->node = xnode;
250
+ return node;
251
+ }
252
+
253
+ /*
254
+ * call-seq:
255
+ * context.find("xpath") -> true|false|number|string|XML::XPath::Object
256
+ *
257
+ * Executes the provided xpath function. The result depends on the execution
258
+ * of the xpath statement. It may be true, false, a number, a string or
259
+ * a node set.
260
+ */
261
+ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
262
+ {
263
+ xmlXPathContextPtr xctxt;
264
+ xmlXPathObjectPtr xobject;
265
+ xmlXPathCompExprPtr xcompexpr;
266
+ VALUE result;
267
+
268
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
269
+
270
+ if (TYPE(xpath_expr) == T_STRING)
271
+ {
272
+ VALUE expression = rb_check_string_type(xpath_expr);
273
+ xobject = xmlXPathEval((xmlChar*) StringValueCStr(expression), xctxt);
274
+ }
275
+ else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression))
276
+ {
277
+ Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr);
278
+ xobject = xmlXPathCompiledEval(xcompexpr, xctxt);
279
+ }
280
+ else
281
+ {
282
+ rb_raise(rb_eTypeError,
283
+ "Argument should be an intance of a String or XPath::Expression");
284
+ }
285
+
286
+ if (xobject == NULL)
287
+ {
288
+ /* xmlLastError is different than xctxt->lastError. Use
289
+ xmlLastError since it has the message set while xctxt->lastError
290
+ does not. */
291
+ xmlErrorPtr xerror = xmlGetLastError();
292
+ rxml_raise(xerror);
293
+ }
294
+
295
+ switch (xobject->type)
296
+ {
297
+ case XPATH_NODESET:
298
+ result = rxml_xpath_object_wrap(xctxt->doc, xobject);
299
+ break;
300
+ case XPATH_BOOLEAN:
301
+ result = (xobject->boolval != 0) ? Qtrue : Qfalse;
302
+ xmlXPathFreeObject(xobject);
303
+ break;
304
+ case XPATH_NUMBER:
305
+ result = rb_float_new(xobject->floatval);
306
+ xmlXPathFreeObject(xobject);
307
+ break;
308
+ case XPATH_STRING:
309
+ result = rb_str_new2((const char*)xobject->stringval);
310
+ xmlXPathFreeObject(xobject);
311
+ break;
312
+ default:
313
+ result = Qnil;
314
+ xmlXPathFreeObject(xobject);
315
+ }
316
+ return result;
317
+ }
318
+
319
+ #if LIBXML_VERSION >= 20626
320
+ /*
321
+ * call-seq:
322
+ * context.enable_cache(size = nil)
323
+ *
324
+ * Enables an XPath::Context's built-in cache. If the cache is
325
+ * enabled then XPath objects will be cached internally for reuse.
326
+ * The size parameter controls sets the maximum number of XPath objects
327
+ * that will be cached per XPath object type (node-set, string, number,
328
+ * boolean, and misc objects). Set size to nil to use the default
329
+ * cache size of 100.
330
+ */
331
+ static VALUE
332
+ rxml_xpath_context_enable_cache(int argc, VALUE *argv, VALUE self)
333
+ {
334
+ xmlXPathContextPtr xctxt;
335
+ VALUE size;
336
+ int value = -1;
337
+
338
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
339
+
340
+ if (rb_scan_args(argc, argv, "01", &size) == 1)
341
+ {
342
+ value = NUM2INT(size);
343
+ }
344
+
345
+ if (xmlXPathContextSetCache(xctxt, 1, value, 0) == -1)
346
+ rxml_raise(&xmlLastError);
347
+
348
+ return self;
349
+ }
350
+
351
+ /*
352
+ * call-seq:
353
+ * context.disable_cache
354
+ *
355
+ * Disables an XPath::Context's built-in cache.
356
+ */
357
+ static VALUE
358
+ rxml_xpath_context_disable_cache(VALUE self)
359
+ {
360
+ xmlXPathContextPtr xctxt;
361
+ Data_Get_Struct(self, xmlXPathContext, xctxt);
362
+
363
+ if (xmlXPathContextSetCache(xctxt, 0, 0, 0) == -1)
364
+ rxml_raise(&xmlLastError);
365
+
366
+ return self;
367
+ }
368
+ #endif
369
+
370
+ void rxml_init_xpath_context(void)
371
+ {
372
+ DOC_ATTRIBUTE = rb_intern("@doc");
373
+
374
+ cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
375
+ rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
376
+ rb_define_attr(cXMLXPathContext, "doc", 1, 0);
377
+ rb_define_method(cXMLXPathContext, "initialize", rxml_xpath_context_initialize, 1);
378
+ rb_define_method(cXMLXPathContext, "register_namespaces", rxml_xpath_context_register_namespaces, 1);
379
+ rb_define_method(cXMLXPathContext, "register_namespaces_from_node", rxml_xpath_context_register_namespaces_from_node, 1);
380
+ rb_define_method(cXMLXPathContext, "register_namespace", rxml_xpath_context_register_namespace, 2);
381
+ rb_define_method(cXMLXPathContext, "node=", rxml_xpath_context_node_set, 1);
382
+ rb_define_method(cXMLXPathContext, "find", rxml_xpath_context_find, 1);
383
+ #if LIBXML_VERSION >= 20626
384
+ rb_define_method(cXMLXPathContext, "enable_cache", rxml_xpath_context_enable_cache, -1);
385
+ rb_define_method(cXMLXPathContext, "disable_cache", rxml_xpath_context_disable_cache, 0);
386
+ #endif
387
+ }