libxml-ruby 2.0.9-x86-mingw32 → 2.1.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY CHANGED
@@ -1,5 +1,30 @@
1
1
  = Release History
2
2
 
3
+ == 2.1.0 / 2011-07-31 Charlie Savage
4
+
5
+ * Ruby 1.9.3 compatability (Charlie Savage).
6
+
7
+ * Added XPath expression <-> Ruby value conversion methods (Jens Wille).
8
+
9
+ * Extracted rxml_xpath_to_value from rxml_xpath_context_find (Jens Wille).
10
+
11
+ * Adapted rxml_xpath_from_value from Gregoire Lejeune's ruby-xslt
12
+ library, see https://github.com/glejeune/ruby-xslt (Jens Wille).
13
+
14
+ * Allow calling #find on nodes returned from Reader (Charlie Savage).
15
+
16
+ * Change document handling in XPath::Context to address segmentation fault on
17
+ Ruby Enterprise Edition (Charlie Savage).
18
+
19
+ * Update gemspec file to work directly with bundler thereby allowing git
20
+ repository to be used as gem (Charlie Savage).
21
+
22
+ * Support gem buld (Charlie Savage).
23
+
24
+ * Simplify memory management of attributes namespaces to fix
25
+ segmentation faults that occurred when using Ruby 1.9.3 (Charlie Savage).
26
+
27
+
3
28
  == 2.0.8 / 2011-06-23 Charlie Savage
4
29
 
5
30
  * Add in 2 new HTML Parser constants - NODEFDTD and NOIMPLIED.
data/Rakefile CHANGED
@@ -4,7 +4,6 @@ require "rubygems"
4
4
  require "rake/extensiontask"
5
5
  require "rake/testtask"
6
6
  require "rubygems/package_task"
7
- ##require 'hanna/rdoctask'
8
7
  require "rdoc/task"
9
8
  require "grancher/task"
10
9
  require "yaml"
@@ -40,6 +39,7 @@ if RUBY_PLATFORM.match(/win32|mingw32/)
40
39
  win_spec = spec.clone
41
40
  win_spec.platform = Gem::Platform::CURRENT
42
41
  win_spec.files += binaries.to_a
42
+ win_spec.instance_variable_set(:@cache_file, nil)
43
43
 
44
44
  # Unset extensions
45
45
  win_spec.extensions = nil
@@ -16,37 +16,11 @@
16
16
  #include <libxml/xmlreader.h>
17
17
  #include <libxml/c14n.h>
18
18
 
19
- /* Needed for Ruby 1.8.5 */
20
- #ifndef RARRAY_LEN
21
- #define RARRAY_LEN(s) (RARRAY(s)->len)
22
- #endif
23
-
24
- /* Needed for Ruby 1.8.5 */
25
- #ifndef RARRAY_PTR
26
- #define RARRAY_PTR(s) (RARRAY(s)->ptr)
27
- #endif
28
-
29
- /* Needed for Ruby 1.8.5 */
30
- #ifndef RSTRING_LEN
31
- #define RSTRING_LEN(s) (RSTRING(s)->len)
32
- #endif
33
-
34
- /* Needed for Ruby 1.8.5 */
35
- #ifndef RSTRING_PTR
36
- #define RSTRING_PTR(s) (RSTRING(s)->ptr)
37
- #endif
38
-
39
19
  /* Needed prior to Ruby 1.9.1 */
40
20
  #ifndef RHASH_TBL
41
21
  #define RHASH_TBL(s) (RHASH(s)->tbl)
42
22
  #endif
43
23
 
44
- // Not in Ruby 1.9
45
- #ifndef GetWriteFile
46
- #define GetWriteFile(fp) rb_io_stdio_file(fp)
47
- #define OpenFile rb_io_t
48
- #endif
49
-
50
24
  // Encoding support added in Ruby 1.9.*
51
25
  #ifdef HAVE_RUBY_ENCODING_H
52
26
  #include <ruby/encoding.h>
@@ -16,57 +16,38 @@
16
16
  * attribute.remove!
17
17
  */
18
18
 
19
+ /* Attributes are owned and freed by their nodes. Thus, its easier for the
20
+ ruby bindings to not manage attribute memory management. This does mean
21
+ that accessing a particular attribute multiple times will return multiple
22
+ different ruby objects. Since we are not using free or xnode->_private
23
+ this works out fine. Previous versions of the bindings had a one to
24
+ one mapping between ruby object and xml attribute, but that could
25
+ result in segfaults because the ruby object could be gc'ed. In theory
26
+ the mark method on the parent node could prevent that, but if an
27
+ attribute is returned using an xpath statement then the node would
28
+ never by surfaced to ruby and the mark method never called. */
29
+
19
30
  #include "ruby_libxml.h"
20
31
  #include "ruby_xml_attr.h"
21
32
 
22
33
  VALUE cXMLAttr;
23
34
 
24
- void rxml_attr_free(xmlAttrPtr xattr)
25
- {
26
- if (!xattr)
27
- return;
28
-
29
- xattr->_private = NULL;
30
-
31
- if (xattr->parent == NULL && xattr->doc == NULL)
32
- {
33
- xmlFreeProp(xattr);
34
- }
35
- }
36
-
37
35
  void rxml_attr_mark(xmlAttrPtr xattr)
38
36
  {
39
37
  /* This can happen if Ruby does a GC run after creating the
40
38
  new attribute but before initializing it. */
41
- if (xattr == NULL)
42
- return;
43
-
44
- if (xattr->_private == NULL)
45
- {
46
- rb_warning("XmlAttr is not bound! (%s:%d)", __FILE__, __LINE__);
47
- return;
48
- }
49
-
50
- rxml_node_mark((xmlNodePtr) xattr);
39
+ if (xattr != NULL)
40
+ rxml_node_mark((xmlNodePtr) xattr);
51
41
  }
52
42
 
53
43
  VALUE rxml_attr_wrap(xmlAttrPtr xattr)
54
44
  {
55
- VALUE result;
56
-
57
- /* Check if the node is already wrapped. */
58
- if (xattr->_private != NULL)
59
- return (VALUE) xattr->_private;
60
-
61
- result = Data_Wrap_Struct(cXMLAttr, rxml_attr_mark, rxml_attr_free, xattr);
62
- xattr->_private = (void*) result;
63
-
64
- return result;
45
+ return Data_Wrap_Struct(cXMLAttr, rxml_attr_mark, NULL, xattr);
65
46
  }
66
47
 
67
48
  static VALUE rxml_attr_alloc(VALUE klass)
68
49
  {
69
- return Data_Wrap_Struct(klass, rxml_attr_mark, rxml_attr_free, NULL);
50
+ return Data_Wrap_Struct(klass, rxml_attr_mark, NULL, NULL);
70
51
  }
71
52
 
72
53
  /*
@@ -116,7 +97,6 @@ static VALUE rxml_attr_initialize(int argc, VALUE *argv, VALUE self)
116
97
  if (!xattr)
117
98
  rb_raise(rb_eRuntimeError, "Could not create attribute.");
118
99
 
119
- xattr->_private = (void *) self;
120
100
  DATA_PTR( self) = xattr;
121
101
  return self;
122
102
  }
@@ -231,7 +211,7 @@ static VALUE rxml_attr_ns_get(VALUE self)
231
211
  if (xattr->ns == NULL)
232
212
  return Qnil;
233
213
  else
234
- return rxml_namespace_wrap(xattr->ns, NULL);
214
+ return rxml_namespace_wrap(xattr->ns);
235
215
  }
236
216
 
237
217
  /*
@@ -268,21 +248,24 @@ static VALUE rxml_attr_prev_get(VALUE self)
268
248
 
269
249
  /*
270
250
  * call-seq:
271
- * node.remove! -> nil
251
+ * attr.remove! -> nil
272
252
  *
273
- * Removes this attribute from it's parent.
253
+ * Removes this attribute from it's parent. Note
254
+ * the attribute and its content is freed and can
255
+ * no longer be used. If you try to use it you
256
+ * will get a segmentation fault.
274
257
  */
275
258
  static VALUE rxml_attr_remove_ex(VALUE self)
276
259
  {
277
260
  xmlAttrPtr xattr;
278
261
  Data_Get_Struct(self, xmlAttr, xattr);
262
+ xmlRemoveProp(xattr);
279
263
 
280
- if (xattr->_private == NULL)
281
- xmlRemoveProp(xattr);
282
- else
283
- xmlUnlinkNode((xmlNodePtr) xattr);
264
+ RDATA(self)->data = NULL;
265
+ RDATA(self)->dfree = NULL;
266
+ RDATA(self)->dmark = NULL;
284
267
 
285
- return Qnil;;
268
+ return Qnil;
286
269
  }
287
270
 
288
271
  /*
@@ -15,28 +15,12 @@ VALUE cXMLAttrDecl;
15
15
 
16
16
  void rxml_attr_decl_mark(xmlAttributePtr xattr)
17
17
  {
18
- if (xattr->_private == NULL)
19
- {
20
- rb_warning("AttrDecl is not bound! (%s:%d)", __FILE__, __LINE__);
21
- return;
22
- }
23
-
24
18
  rxml_node_mark((xmlNodePtr) xattr);
25
19
  }
26
20
 
27
21
  VALUE rxml_attr_decl_wrap(xmlAttributePtr xattr)
28
22
  {
29
- VALUE result;
30
-
31
- // This node is already wrapped
32
- if (xattr->_private != NULL)
33
- return (VALUE) xattr->_private;
34
-
35
- result = Data_Wrap_Struct(cXMLAttrDecl, rxml_attr_decl_mark, NULL, xattr);
36
-
37
- xattr->_private = (void*) result;
38
-
39
- return result;
23
+ return Data_Wrap_Struct(cXMLAttrDecl, rxml_attr_decl_mark, NULL, xattr);
40
24
  }
41
25
 
42
26
  /*
@@ -21,32 +21,17 @@ VALUE cXMLNamespace;
21
21
  * assert_nil(node.namespaces.namespace)
22
22
  */
23
23
 
24
- static void rxml_namespace_free(xmlNsPtr xns)
25
- {
26
- xns->_private = NULL;
27
- }
24
+ /* Namespaces are owned and freed by their nodes. Thus, its easier for the
25
+ ruby bindings to not manage attribute memory management. */
28
26
 
29
27
  static VALUE rxml_namespace_alloc(VALUE klass)
30
28
  {
31
- return Data_Wrap_Struct(klass, NULL, rxml_namespace_free, NULL);
29
+ return Data_Wrap_Struct(klass, NULL, NULL, NULL);
32
30
  }
33
31
 
34
- VALUE rxml_namespace_wrap(xmlNsPtr xns, RUBY_DATA_FUNC freeFunc)
32
+ VALUE rxml_namespace_wrap(xmlNsPtr xns)
35
33
  {
36
- if (xns->_private)
37
- {
38
- return (VALUE)xns->_private;
39
- }
40
- else
41
- {
42
- VALUE ns;
43
- if (freeFunc == NULL)
44
- freeFunc = (RUBY_DATA_FUNC)rxml_namespace_free;
45
-
46
- ns = Data_Wrap_Struct(cXMLNamespace, NULL, freeFunc, xns);
47
- xns->_private = (void*)ns;
48
- return ns;
49
- }
34
+ return Data_Wrap_Struct(cXMLNamespace, NULL, NULL, xns);
50
35
  }
51
36
 
52
37
  static VALUE rxml_namespace_string(xmlNsPtr xns, const char* buffer)
@@ -84,7 +69,6 @@ static VALUE rxml_namespace_initialize(VALUE self, VALUE node, VALUE prefix,
84
69
  if (!xns)
85
70
  rxml_raise(&xmlLastError);
86
71
 
87
- xns->_private = (void*)self;
88
72
  DATA_PTR(self) = xns;
89
73
  return self;
90
74
  }
@@ -163,7 +147,7 @@ static VALUE rxml_namespace_next(VALUE self)
163
147
  if (xns == NULL || xns->next == NULL)
164
148
  return (Qnil);
165
149
  else
166
- return (rxml_namespace_wrap(xns->next, NULL));
150
+ return rxml_namespace_wrap(xns->next);
167
151
  }
168
152
 
169
153
  void rxml_init_namespace(void)
@@ -6,5 +6,5 @@
6
6
  extern VALUE cXMLNamespace;
7
7
 
8
8
  void rxml_init_namespace(void);
9
- VALUE rxml_namespace_wrap(xmlNsPtr xns, RUBY_DATA_FUNC freeFunc);
9
+ VALUE rxml_namespace_wrap(xmlNsPtr xns);
10
10
  #endif
@@ -90,7 +90,7 @@ static VALUE rxml_namespaces_definitions(VALUE self)
90
90
 
91
91
  while (xns)
92
92
  {
93
- VALUE anamespace = rxml_namespace_wrap(xns, NULL);
93
+ VALUE anamespace = rxml_namespace_wrap(xns);
94
94
  rb_ary_push(arr, anamespace);
95
95
  xns = xns->next;
96
96
  }
@@ -126,7 +126,7 @@ static VALUE rxml_namespaces_each(VALUE self)
126
126
 
127
127
  for (xns = nsList; *xns != NULL; xns++)
128
128
  {
129
- VALUE ns = rxml_namespace_wrap(*xns, NULL);
129
+ VALUE ns = rxml_namespace_wrap(*xns);
130
130
  rb_yield(ns);
131
131
  }
132
132
  xmlFree(nsList);
@@ -161,7 +161,7 @@ static VALUE rxml_namespaces_find_by_href(VALUE self, VALUE href)
161
161
 
162
162
  xns = xmlSearchNsByHref(xnode->doc, xnode, (xmlChar*) StringValuePtr(href));
163
163
  if (xns)
164
- return rxml_namespace_wrap(xns, NULL);
164
+ return rxml_namespace_wrap(xns);
165
165
  else
166
166
  return Qnil;
167
167
  }
@@ -200,7 +200,7 @@ static VALUE rxml_namespaces_find_by_prefix(VALUE self, VALUE prefix)
200
200
 
201
201
  xns = xmlSearchNs(xnode->doc, xnode, xprefix);
202
202
  if (xns)
203
- return rxml_namespace_wrap(xns, NULL);
203
+ return rxml_namespace_wrap(xns);
204
204
  else
205
205
  return Qnil;
206
206
  }
@@ -224,7 +224,7 @@ static VALUE rxml_namespaces_namespace_get(VALUE self)
224
224
  Data_Get_Struct(self, xmlNode, xnode);
225
225
 
226
226
  if (xnode->ns)
227
- return rxml_namespace_wrap(xnode->ns, NULL);
227
+ return rxml_namespace_wrap(xnode->ns);
228
228
  else
229
229
  return Qnil;
230
230
  }
@@ -508,8 +508,7 @@ static VALUE rxml_node_doc(VALUE self)
508
508
  else if (xdoc->_private)
509
509
  return (VALUE) xdoc->_private;
510
510
  else
511
- /* This can happen by calling Reader#expand.doc */
512
- rb_raise(eXMLError, "Document is not accessible to Ruby (hint - did you call Reader#expand?)");
511
+ return (Qnil);
513
512
  }
514
513
 
515
514
  /*
@@ -350,7 +350,7 @@ static VALUE rxml_parser_context_encoding_set(VALUE self, VALUE encoding)
350
350
  xmlCharEncodingHandlerPtr hdlr = xmlFindCharEncodingHandler(xencoding);
351
351
 
352
352
  if (!hdlr)
353
- rb_raise(rb_eRuntimeError, "Unknown encoding: %s", encoding);
353
+ rb_raise(rb_eArgError, "Unknown encoding: %i", NUM2INT(encoding));
354
354
 
355
355
  Data_Get_Struct(self, xmlParserCtxt, ctxt);
356
356
  result = xmlSwitchToEncoding(ctxt, hdlr);
@@ -42,6 +42,11 @@
42
42
  *
43
43
  * For a more in depth tutorial, albeit in C, see http://xmlsoft.org/xmlreader.html.*/
44
44
 
45
+
46
+ /* NOTE - We need to wrap the readers document to support Reader.read.node.find('/').
47
+ To do this we need to use xmlTextReaderCurrentDoc which means we have to free the
48
+ document ourselves. Annoying... */
49
+
45
50
  VALUE cXMLReader;
46
51
 
47
52
  static ID BASE_URI_SYMBOL;
@@ -54,11 +59,20 @@ static void rxml_reader_free(xmlTextReaderPtr xreader)
54
59
  xmlFreeTextReader(xreader);
55
60
  }
56
61
 
62
+ static void rxml_reader_mark(xmlTextReaderPtr xreader)
63
+ {
64
+ xmlDocPtr xdoc = xmlTextReaderCurrentDoc(xreader);
65
+
66
+ if (xdoc && xdoc->_private)
67
+ rb_gc_mark((VALUE) xdoc->_private);
68
+ }
69
+
57
70
  static VALUE rxml_reader_wrap(xmlTextReaderPtr xreader)
58
71
  {
59
72
  return Data_Wrap_Struct(cXMLReader, NULL, rxml_reader_free, xreader);
60
73
  }
61
74
 
75
+
62
76
  static xmlTextReaderPtr rxml_text_reader_get(VALUE obj)
63
77
  {
64
78
  xmlTextReaderPtr xreader;
@@ -414,7 +428,7 @@ static VALUE rxml_reader_normalization(VALUE self)
414
428
 
415
429
  /*
416
430
  * call-seq:
417
- * reader.read -> code
431
+ * reader.read -> nil|true|false
418
432
  *
419
433
  * Causes the reader to move to the next node in the stream, exposing its properties.
420
434
  *
@@ -873,7 +887,15 @@ static VALUE rxml_reader_lookup_namespace(VALUE self, VALUE prefix)
873
887
  static VALUE rxml_reader_expand(VALUE self)
874
888
  {
875
889
  xmlTextReaderPtr xreader = rxml_text_reader_get(self);
876
- xmlNodePtr xnode = xmlTextReaderExpand(xreader);
890
+ xmlNodePtr xnode = NULL;
891
+
892
+ /* At this point we need to wrap the reader's document as explained above. */
893
+ rxml_document_wrap(xmlTextReaderCurrentDoc(xreader));
894
+
895
+ /* And now hook in a mark function */
896
+ RDATA(self)->dmark = (RUBY_DATA_FUNC)rxml_reader_mark;
897
+
898
+ xnode = xmlTextReaderExpand(xreader);
877
899
 
878
900
  if (!xnode)
879
901
  {
@@ -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 "2.0.9"
5
- #define RUBY_LIBXML_VERNUM 209
4
+ #define RUBY_LIBXML_VERSION "2.1.0"
5
+ #define RUBY_LIBXML_VERNUM 210
6
6
  #define RUBY_LIBXML_VER_MAJ 2
7
- #define RUBY_LIBXML_VER_MIN 0
8
- #define RUBY_LIBXML_VER_MIC 9
7
+ #define RUBY_LIBXML_VER_MIN 1
8
+ #define RUBY_LIBXML_VER_MIC 0
9
9
  #define RUBY_LIBXML_VER_PATCH 0
@@ -78,6 +78,88 @@
78
78
 
79
79
  VALUE mXPath;
80
80
 
81
+ VALUE
82
+ rxml_xpath_to_value(xmlXPathContextPtr xctxt, xmlXPathObjectPtr xobject) {
83
+ VALUE result;
84
+ int type;
85
+
86
+ if (xobject == NULL) {
87
+ /* xmlLastError is different than xctxt->lastError. Use
88
+ xmlLastError since it has the message set while xctxt->lastError
89
+ does not. */
90
+ xmlErrorPtr xerror = xmlGetLastError();
91
+ rxml_raise(xerror);
92
+ }
93
+
94
+ switch (type = xobject->type) {
95
+ case XPATH_NODESET:
96
+ result = rxml_xpath_object_wrap(xctxt->doc, xobject);
97
+ break;
98
+ case XPATH_BOOLEAN:
99
+ result = (xobject->boolval != 0) ? Qtrue : Qfalse;
100
+ xmlXPathFreeObject(xobject);
101
+ break;
102
+ case XPATH_NUMBER:
103
+ result = rb_float_new(xobject->floatval);
104
+ xmlXPathFreeObject(xobject);
105
+ break;
106
+ case XPATH_STRING:
107
+ result = rxml_str_new2((const char*)xobject->stringval, xctxt->doc->encoding);
108
+ xmlXPathFreeObject(xobject);
109
+ break;
110
+ default:
111
+ xmlXPathFreeObject(xobject);
112
+ rb_raise(rb_eTypeError,
113
+ "can't convert XPath object of type %d to Ruby value", type
114
+ );
115
+ }
116
+
117
+ return result;
118
+ }
119
+
120
+ xmlXPathObjectPtr
121
+ rxml_xpath_from_value(VALUE value) {
122
+ xmlXPathObjectPtr result = NULL;
123
+
124
+ switch (TYPE(value)) {
125
+ case T_TRUE:
126
+ case T_FALSE:
127
+ result = xmlXPathNewBoolean(RTEST(value));
128
+ break;
129
+ case T_FIXNUM:
130
+ case T_FLOAT:
131
+ result = xmlXPathNewFloat(NUM2DBL(value));
132
+ break;
133
+ case T_STRING:
134
+ result = xmlXPathWrapString(xmlStrdup((const xmlChar *)StringValuePtr(value)));
135
+ break;
136
+ case T_NIL:
137
+ result = xmlXPathNewNodeSet(NULL);
138
+ break;
139
+ case T_ARRAY: {
140
+ int i, j;
141
+ result = xmlXPathNewNodeSet(NULL);
142
+
143
+ for (i = RARRAY_LEN(value); i > 0; i--) {
144
+ xmlXPathObjectPtr obj = rxml_xpath_from_value(rb_ary_shift(value));
145
+
146
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
147
+ for (j = 0; j < obj->nodesetval->nodeNr; j++) {
148
+ xmlXPathNodeSetAdd(result->nodesetval, obj->nodesetval->nodeTab[j]);
149
+ }
150
+ }
151
+ }
152
+ break;
153
+ }
154
+ default:
155
+ rb_raise(rb_eTypeError,
156
+ "can't convert object of type %s to XPath object", rb_obj_classname(value)
157
+ );
158
+ }
159
+
160
+ return result;
161
+ }
162
+
81
163
  void rxml_init_xpath(void)
82
164
  {
83
165
  mXPath = rb_define_module_under(mXML, "XPath");
@@ -5,6 +5,9 @@
5
5
 
6
6
  extern VALUE mXPath;
7
7
 
8
+ extern VALUE rxml_xpath_to_value(xmlXPathContextPtr, xmlXPathObjectPtr);
9
+ extern xmlXPathObjectPtr rxml_xpath_from_value(VALUE);
10
+
8
11
  void rxml_init_xpath(void);
9
12
 
10
13
  #endif
@@ -26,16 +26,20 @@
26
26
 
27
27
  VALUE cXMLXPathContext;
28
28
 
29
- static ID DOC_ATTRIBUTE;
30
-
31
29
  static void rxml_xpath_context_free(xmlXPathContextPtr ctxt)
32
30
  {
33
31
  xmlXPathFreeContext(ctxt);
34
32
  }
35
33
 
34
+ static void rxml_xpath_context_mark(xmlXPathContextPtr ctxt)
35
+ {
36
+ if (ctxt->doc->_private)
37
+ rb_gc_mark((VALUE) ctxt->doc->_private);
38
+ }
39
+
36
40
  static VALUE rxml_xpath_context_alloc(VALUE klass)
37
41
  {
38
- return Data_Wrap_Struct(cXMLXPathContext, NULL, rxml_xpath_context_free, NULL);
42
+ return Data_Wrap_Struct(cXMLXPathContext, rxml_xpath_context_mark, rxml_xpath_context_free, NULL);
39
43
  }
40
44
 
41
45
  /* call-seq:
@@ -72,12 +76,25 @@ static VALUE rxml_xpath_context_initialize(VALUE self, VALUE node)
72
76
  Data_Get_Struct(document, xmlDoc, xdoc);
73
77
  DATA_PTR(self) = xmlXPathNewContext(xdoc);
74
78
 
75
- /* Save the doc as an attribute, this will expose it to Ruby's GC. */
76
- rb_ivar_set(self, DOC_ATTRIBUTE, document);
77
-
78
79
  return self;
79
80
  }
80
81
 
82
+ /*
83
+ * call-seq:
84
+ * context.doc -> document
85
+ *
86
+ * Obtain the XML::Document this node belongs to.
87
+ */
88
+ static VALUE rxml_xpath_context_doc(VALUE self)
89
+ {
90
+ xmlDocPtr xdoc = NULL;
91
+ xmlXPathContextPtr ctxt;
92
+ Data_Get_Struct(self, xmlXPathContext, ctxt);
93
+
94
+ xdoc = ctxt->doc;
95
+ return rxml_document_wrap(xdoc);
96
+ }
97
+
81
98
  /*
82
99
  * call-seq:
83
100
  * context.register_namespace(prefix, uri) -> (true|false)
@@ -264,7 +281,6 @@ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
264
281
  xmlXPathContextPtr xctxt;
265
282
  xmlXPathObjectPtr xobject;
266
283
  xmlXPathCompExprPtr xcompexpr;
267
- VALUE result;
268
284
 
269
285
  Data_Get_Struct(self, xmlXPathContext, xctxt);
270
286
 
@@ -284,37 +300,7 @@ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
284
300
  "Argument should be an intance of a String or XPath::Expression");
285
301
  }
286
302
 
287
- if (xobject == NULL)
288
- {
289
- /* xmlLastError is different than xctxt->lastError. Use
290
- xmlLastError since it has the message set while xctxt->lastError
291
- does not. */
292
- xmlErrorPtr xerror = xmlGetLastError();
293
- rxml_raise(xerror);
294
- }
295
-
296
- switch (xobject->type)
297
- {
298
- case XPATH_NODESET:
299
- result = rxml_xpath_object_wrap(xctxt->doc, xobject);
300
- break;
301
- case XPATH_BOOLEAN:
302
- result = (xobject->boolval != 0) ? Qtrue : Qfalse;
303
- xmlXPathFreeObject(xobject);
304
- break;
305
- case XPATH_NUMBER:
306
- result = rb_float_new(xobject->floatval);
307
- xmlXPathFreeObject(xobject);
308
- break;
309
- case XPATH_STRING:
310
- result = rxml_str_new2((const char*)xobject->stringval, xctxt->doc->encoding);
311
- xmlXPathFreeObject(xobject);
312
- break;
313
- default:
314
- result = Qnil;
315
- xmlXPathFreeObject(xobject);
316
- }
317
- return result;
303
+ return rxml_xpath_to_value(xctxt, xobject);
318
304
  }
319
305
 
320
306
  #if LIBXML_VERSION >= 20626
@@ -370,11 +356,9 @@ rxml_xpath_context_disable_cache(VALUE self)
370
356
 
371
357
  void rxml_init_xpath_context(void)
372
358
  {
373
- DOC_ATTRIBUTE = rb_intern("@doc");
374
-
375
359
  cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
376
360
  rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
377
- rb_define_attr(cXMLXPathContext, "doc", 1, 0);
361
+ rb_define_method(cXMLXPathContext, "doc", rxml_xpath_context_doc, 0);
378
362
  rb_define_method(cXMLXPathContext, "initialize", rxml_xpath_context_initialize, 1);
379
363
  rb_define_method(cXMLXPathContext, "register_namespaces", rxml_xpath_context_register_namespaces, 1);
380
364
  rb_define_method(cXMLXPathContext, "register_namespaces_from_node", rxml_xpath_context_register_namespaces_from_node, 1);
@@ -45,7 +45,6 @@ static void rxml_xpath_object_free(rxml_xpath_object *rxpop)
45
45
  /* Custom free function for copied namespace nodes */
46
46
  static void rxml_namespace_xpath_free(xmlNsPtr xns)
47
47
  {
48
- xns->_private = NULL;
49
48
  xmlFreeNs(xns);
50
49
  }
51
50
 
@@ -82,7 +81,8 @@ VALUE rxml_xpath_object_wrap(xmlDocPtr xdoc, xmlXPathObjectPtr xpop)
82
81
 
83
82
  /* Specify a custom free function here since by default
84
83
  namespace nodes will not be freed */
85
- ns = rxml_namespace_wrap((xmlNsPtr)xnode, (RUBY_DATA_FUNC)rxml_namespace_xpath_free);
84
+ ns = rxml_namespace_wrap((xmlNsPtr)xnode);
85
+ RDATA(ns)->dfree = (RUBY_DATA_FUNC)rxml_namespace_xpath_free;
86
86
  rb_ary_push(rxpop->nsnodes, ns);
87
87
  }
88
88
  }
@@ -93,7 +93,6 @@ VALUE rxml_xpath_object_wrap(xmlDocPtr xdoc, xmlXPathObjectPtr xpop)
93
93
 
94
94
  static VALUE rxml_xpath_object_tabref(xmlXPathObjectPtr xpop, int apos)
95
95
  {
96
-
97
96
  if (apos < 0)
98
97
  apos = xpop->nodesetval->nodeNr + apos;
99
98
 
@@ -106,7 +105,7 @@ static VALUE rxml_xpath_object_tabref(xmlXPathObjectPtr xpop, int apos)
106
105
  return rxml_attr_wrap((xmlAttrPtr) xpop->nodesetval->nodeTab[apos]);
107
106
  break;
108
107
  case XML_NAMESPACE_DECL:
109
- return rxml_namespace_wrap((xmlNsPtr)xpop->nodesetval->nodeTab[apos], NULL);
108
+ return rxml_namespace_wrap((xmlNsPtr)xpop->nodesetval->nodeTab[apos]);
110
109
  break;
111
110
  default:
112
111
  return rxml_node_wrap(xpop->nodesetval->nodeTab[apos]);
Binary file
Binary file
data/libxml-ruby.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ require 'rake'
2
3
 
3
4
  # Determine the current version of the software
4
5
  version = File.read('ext/libxml/ruby_xml_version.h').match(/\s*RUBY_LIBXML_VERSION\s*['"](\d.+)['"]/)[1]
data/test/tc_attr.rb CHANGED
@@ -27,6 +27,7 @@ class AttrNodeTest < Test::Unit::TestCase
27
27
 
28
28
  def teardown
29
29
  @doc = nil
30
+ GC.start
30
31
  end
31
32
 
32
33
  def city_member
@@ -37,117 +38,118 @@ class AttrNodeTest < Test::Unit::TestCase
37
38
  assert_not_nil(@doc)
38
39
  assert_equal(XML::Encoding::NONE, @doc.encoding)
39
40
  end
40
-
41
+
41
42
  def test_types
42
43
  attribute = city_member.attributes.get_attribute('name')
43
44
  assert_instance_of(XML::Attr, attribute)
44
45
  assert_equal('attribute', attribute.node_type_name)
45
46
  end
46
-
47
+
47
48
  def test_name
48
49
  attribute = city_member.attributes.get_attribute('name')
49
50
  assert_equal('name', attribute.name)
50
51
  assert_equal(Encoding::ASCII_8BIT, attribute.name.encoding) if defined?(Encoding)
51
-
52
+
52
53
  attribute = city_member.attributes.get_attribute('href')
53
54
  assert_equal('href', attribute.name)
54
55
  assert_equal('xlink', attribute.ns.prefix)
55
56
  assert_equal('http://www.w3.org/1999/xlink', attribute.ns.href)
56
-
57
+
57
58
  attribute = city_member.attributes.get_attribute_ns('http://www.w3.org/1999/xlink', 'href')
58
59
  assert_equal('href', attribute.name)
59
60
  assert_equal('xlink', attribute.ns.prefix)
60
61
  assert_equal('http://www.w3.org/1999/xlink', attribute.ns.href)
61
62
  end
62
-
63
+
63
64
  def test_value
64
65
  attribute = city_member.attributes.get_attribute('name')
65
66
  assert_equal('Cambridge', attribute.value)
66
67
  assert_equal(Encoding::ASCII_8BIT, attribute.value.encoding) if defined?(Encoding)
67
-
68
+
68
69
  attribute = city_member.attributes.get_attribute('href')
69
70
  assert_equal('http://www.foo.net/cgi-bin/wfs?FeatureID=C10239', attribute.value)
70
71
  end
71
-
72
+
72
73
  def test_set_value
73
74
  attribute = city_member.attributes.get_attribute('name')
74
75
  attribute.value = 'London'
75
76
  assert_equal('London', attribute.value)
76
77
  assert_equal(Encoding::ASCII_8BIT, attribute.value.encoding) if defined?(Encoding)
77
-
78
+
78
79
  attribute = city_member.attributes.get_attribute('href')
79
80
  attribute.value = 'http://i.have.changed'
80
81
  assert_equal('http://i.have.changed', attribute.value)
81
82
  assert_equal(Encoding::ASCII_8BIT, attribute.value.encoding) if defined?(Encoding)
82
83
  end
83
-
84
+
84
85
  def test_set_nil
85
86
  attribute = city_member.attributes.get_attribute('name')
86
87
  assert_raise(TypeError) do
87
88
  attribute.value = nil
88
89
  end
89
90
  end
90
-
91
+
91
92
  def test_create
92
93
  attributes = city_member.attributes
93
94
  assert_equal(5, attributes.length)
94
-
95
+
95
96
  attr = XML::Attr.new(city_member, 'size', '50,000')
96
97
  assert_instance_of(XML::Attr, attr)
97
-
98
+
98
99
  attributes = city_member.attributes
99
100
  assert_equal(6, attributes.length)
100
-
101
+
101
102
  assert_equal(attributes['size'], '50,000')
102
103
  end
103
-
104
+
104
105
  def test_create_on_node
105
106
  attributes = city_member.attributes
106
107
  assert_equal(5, attributes.length)
107
-
108
+
108
109
  attributes['country'] = 'England'
109
-
110
+
110
111
  attributes = city_member.attributes
111
112
  assert_equal(6, attributes.length)
112
-
113
+
113
114
  assert_equal(attributes['country'], 'England')
114
115
  end
115
-
116
+
116
117
  def test_create_ns
117
118
  assert_equal(5, city_member.attributes.length)
118
-
119
+
119
120
  ns = XML::Namespace.new(city_member, 'my_namepace', 'http://www.mynamespace.com')
120
121
  attr = XML::Attr.new(city_member, 'rating', 'rocks', ns)
121
122
  assert_instance_of(XML::Attr, attr)
122
123
  assert_equal('rating', attr.name)
123
124
  assert_equal('rocks', attr.value)
124
-
125
+
125
126
  attributes = city_member.attributes
126
127
  assert_equal(6, attributes.length)
127
-
128
+
128
129
  assert_equal('rocks', city_member['rating'])
129
130
  end
130
131
 
131
132
  def test_remove
132
133
  attributes = city_member.attributes
133
134
  assert_equal(5, attributes.length)
134
-
135
+
135
136
  attribute = attributes.get_attribute('name')
136
137
  assert_not_nil(attribute.parent)
137
138
  assert(attribute.parent?)
138
-
139
+
139
140
  attribute.remove!
140
141
  assert_equal(4, attributes.length)
141
- assert_nil(attribute.parent)
142
- assert(!attribute.parent?)
142
+
143
+ attribute = attributes.get_attribute('name')
144
+ assert_nil(attribute)
143
145
  end
144
-
146
+
145
147
  def test_first
146
148
  attribute = city_member.attributes.first
147
149
  assert_instance_of(XML::Attr, attribute)
148
150
  assert_equal('name', attribute.name)
149
151
  assert_equal('Cambridge', attribute.value)
150
-
152
+
151
153
  attribute = attribute.next
152
154
  assert_instance_of(XML::Attr, attribute)
153
155
  assert_equal('type', attribute.name)
@@ -157,7 +159,7 @@ class AttrNodeTest < Test::Unit::TestCase
157
159
  assert_instance_of(XML::Attr, attribute)
158
160
  assert_equal('title', attribute.name)
159
161
  assert_equal('Trinity Lane', attribute.value)
160
-
162
+
161
163
  attribute = attribute.next
162
164
  assert_instance_of(XML::Attr, attribute)
163
165
  assert_equal('href', attribute.name)
@@ -167,7 +169,7 @@ class AttrNodeTest < Test::Unit::TestCase
167
169
  assert_instance_of(XML::Attr, attribute)
168
170
  assert_equal('remoteSchema', attribute.name)
169
171
  assert_equal("city.xsd#xpointer(//complexType[@name='RoadType'])", attribute.value)
170
-
172
+
171
173
  attribute = attribute.next
172
174
  assert_nil(attribute)
173
175
  end
@@ -6,7 +6,7 @@ require 'test/unit'
6
6
  class AttributesTest < Test::Unit::TestCase
7
7
  def setup
8
8
  xp = XML::Parser.string(<<-EOS)
9
- <CityModel
9
+ <CityModel name="value"
10
10
  xmlns="http://www.opengis.net/examples"
11
11
  xmlns:city="http://www.opengis.net/examples"
12
12
  xmlns:gml="http://www.opengis.net/gml"
@@ -90,6 +90,14 @@ class AttributesTest < Test::Unit::TestCase
90
90
  assert_equal('http://www.foo.net/cgi-bin/wfs?FeatureID=C10239', attributes[:href])
91
91
  end
92
92
 
93
+ def test_get_values_gc
94
+ # There used to be a bug caused by accessing an
95
+ # attribute over and over and over again.
96
+ 20000.times do
97
+ @doc.root.attributes["key"]
98
+ end
99
+ end
100
+
93
101
  def test_set_values
94
102
  city_member[:name] = 'London'
95
103
  assert_equal('London', city_member[:name])
@@ -34,6 +34,22 @@ class TestParserContext < Test::Unit::TestCase
34
34
  assert_equal(XML::Encoding::ISO_8859_1, context.encoding)
35
35
  end
36
36
 
37
+ def test_invalid_encoding
38
+ # UTF8
39
+ xml = <<-EOS
40
+ <bands>
41
+ <metal>m\303\266tley_cr\303\274e</metal>
42
+ </bands>
43
+ EOS
44
+
45
+ context = XML::Parser::Context.string(xml)
46
+
47
+ error = assert_raise(ArgumentError) do
48
+ context.encoding = -999
49
+ end
50
+ assert_equal("Unknown encoding: -999", error.to_s)
51
+ end
52
+
37
53
  def test_base_uri
38
54
  # UTF8
39
55
  xml = <<-EOS
@@ -51,7 +67,7 @@ class TestParserContext < Test::Unit::TestCase
51
67
 
52
68
  def test_string_empty
53
69
  error = assert_raise(TypeError) do
54
- parser = XML::Parser::Context.string(nil)
70
+ XML::Parser::Context.string(nil)
55
71
  end
56
72
  assert_equal("wrong argument type nil (expected String)", error.to_s)
57
73
 
data/test/tc_reader.rb CHANGED
@@ -171,12 +171,33 @@ class TestReader < Test::Unit::TestCase
171
171
  node = reader.expand
172
172
  assert_equal('feed', node.name)
173
173
  assert_equal(::Encoding::UTF_8, node.name.encoding) if defined?(::Encoding)
174
+ end
175
+
176
+ def test_expand_doc
177
+ reader = XML::Reader.file(XML_FILE)
178
+ reader.read.to_s
179
+ reader.read
180
+
181
+ # Read a node
182
+ node = reader.expand
174
183
 
175
184
  # Try to access the document
176
- error = assert_raise(XML::Error) do
177
- assert_not_nil(node.doc)
178
- end
179
- assert_equal(" Document is not accessible to Ruby (hint - did you call Reader#expand?).", error.to_s)
185
+ assert_not_nil(node.doc)
186
+ end
187
+
188
+ def test_expand_find
189
+ reader = XML::Reader.file(XML_FILE)
190
+ reader.read.to_s
191
+ reader.read
192
+
193
+ # Read first node which
194
+ node = reader.expand
195
+ assert_equal('feed', node.name)
196
+
197
+ # Search for entries
198
+ entries = node.find('atom:entry', 'atom:http://www.w3.org/2005/Atom')
199
+
200
+ assert_equal(1, entries.length)
180
201
  end
181
202
 
182
203
  def test_mode
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libxml-ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
+ - 1
8
9
  - 0
9
- - 9
10
- version: 2.0.9
10
+ version: 2.1.0
11
11
  platform: x86-mingw32
12
12
  authors:
13
13
  - Ross Bamform
@@ -20,7 +20,7 @@ autorequire:
20
20
  bindir: bin
21
21
  cert_chain: []
22
22
 
23
- date: 2011-06-25 00:00:00 Z
23
+ date: 2011-07-31 00:00:00 Z
24
24
  dependencies: []
25
25
 
26
26
  description: " The Libxml-Ruby project provides Ruby language bindings for the GNOME\n Libxml2 XML toolkit. It is free software, released under the MIT License.\n Libxml-ruby's primary advantage over REXML is performance - if speed\n is your need, these are good libraries to consider, as demonstrated\n by the informal benchmark below.\n"
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  requirements: []
228
228
 
229
229
  rubyforge_project:
230
- rubygems_version: 1.7.2
230
+ rubygems_version: 1.8.6
231
231
  signing_key:
232
232
  specification_version: 3
233
233
  summary: Ruby Bindings for LibXML2