libxml-ruby 2.0.2-x86-mingw32 → 2.0.3-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +52 -1
- data/README.rdoc +40 -10
- data/ext/libxml/ruby_libxml.h +1 -0
- data/ext/libxml/ruby_xml_attr.c +2 -2
- data/ext/libxml/ruby_xml_document.c +57 -7
- data/ext/libxml/ruby_xml_error.c +0 -12
- data/ext/libxml/ruby_xml_node.c +107 -92
- data/ext/libxml/ruby_xml_reader.c +1085 -1057
- data/ext/libxml/ruby_xml_schema.c +2 -53
- data/ext/libxml/ruby_xml_version.h +3 -3
- data/lib/1.8/libxml_ruby.so +0 -0
- data/lib/1.9/libxml_ruby.so +0 -0
- data/test/tc_document.rb +43 -6
- data/test/tc_document_write.rb +15 -1
- data/test/tc_error.rb +33 -21
- data/test/tc_node.rb +11 -0
- data/test/tc_node_edit.rb +19 -3
- data/test/tc_parser.rb +16 -1
- data/test/tc_reader.rb +11 -3
- data/test/tc_sax_parser.rb +45 -1
- data/test/test_suite.rb +4 -2
- metadata +16 -6
- data/test/rb-magic-comment.rb +0 -33
data/HISTORY
CHANGED
@@ -1,6 +1,57 @@
|
|
1
1
|
= Release History
|
2
2
|
|
3
|
-
== 2.0.
|
3
|
+
== 2.0.3 / 2011-05-01 Charlie Savage
|
4
|
+
|
5
|
+
* The biggest change in this release is supporting the use of libxml-ruby in
|
6
|
+
native background Ruby threads. Previously, the use of libxml-ruby in
|
7
|
+
background threads in Ruby 1.9.x and higher would often cause
|
8
|
+
segmentation faults. This has now been fixed (Charlie Savage).
|
9
|
+
|
10
|
+
* Update Reader#expand so that returned node correctly remembers its
|
11
|
+
encoding in Ruby 1.9.x (zerebubuth).
|
12
|
+
|
13
|
+
* Add check to verify a node has not been deleted. This can happen when
|
14
|
+
a ruby variable holds a reference to a child node that gets freed
|
15
|
+
when its parent gets freed. Previously when this happened a
|
16
|
+
segmentation fault would occur, now an exception is raised (Charlie Savage, fixes
|
17
|
+
RubyForge #26839.
|
18
|
+
|
19
|
+
* Do not unlink nodes before internal validations have run - avoids
|
20
|
+
segmentation faults caused by freeing a node twice (Charlie Savage).
|
21
|
+
|
22
|
+
* Add support for Document#canonicalization (Victor Lin).
|
23
|
+
|
24
|
+
* Fix memory leak in Reader#lookup_namespace (Charlie Savage).
|
25
|
+
|
26
|
+
* Fix memory leak in Reader#[] (Nathan Kriege).
|
27
|
+
|
28
|
+
* Fix usage of @io instance variable (Jeffrey Taylor)
|
29
|
+
|
30
|
+
* Removed old sax error handling code that has been fixed in newer
|
31
|
+
versions of libxml (Charlie Savage).
|
32
|
+
|
33
|
+
* Code cleanup - remove unused variables and commented out code (Charlie Savage)
|
34
|
+
|
35
|
+
* Minor text changes and documentation fixes (Charlie Savage).
|
36
|
+
|
37
|
+
* Fix documentation error (fixes RubyForge #26888).
|
38
|
+
|
39
|
+
* Update documentation for Document#validation* methods (fixes RubyForge #24833).
|
40
|
+
|
41
|
+
* Update documentation and test (fixes Ruby Forge Issue #28770).
|
42
|
+
|
43
|
+
* Updated documentation in README (Anurag Priyam):
|
44
|
+
1. rake doc does not work; use rake rdoc.
|
45
|
+
2. gem mislav-hanna does not exist; use hanna.
|
46
|
+
3. rake rdoc 'depends' on hanna; no need of RDOCOPTS
|
47
|
+
4. Point to the github issue tracker instead of Ruby Forge
|
48
|
+
5. Point to the github (gh-pages) site for docs
|
49
|
+
|
50
|
+
* Add tc_error to test suite (Charlie Savage).
|
51
|
+
|
52
|
+
* Add sax test (Stanislav O.Pogrebnyak).
|
53
|
+
|
54
|
+
== 2.0.2 / 2011-04-17 Charlie Savage
|
4
55
|
|
5
56
|
* Added binaries for windows (Charlie Savage).
|
6
57
|
|
data/README.rdoc
CHANGED
@@ -75,9 +75,9 @@ then install the libxslt gem which is available at
|
|
75
75
|
http://rubyforge.org/projects/libxsl/.
|
76
76
|
|
77
77
|
== Usage
|
78
|
-
For information about using libxml-ruby please refer
|
79
|
-
|
80
|
-
|
78
|
+
For information about using libxml-ruby please refer to its documentation at
|
79
|
+
http://xml4r.github.com/libxml-ruby/rdoc/index.html Some tutorials are also
|
80
|
+
available at https://github.com/xml4r/libxml-ruby/wiki.
|
81
81
|
|
82
82
|
All libxml classes are in the LibXML::XML module. The easiest
|
83
83
|
way to use libxml is to require 'xml'. This will mixin
|
@@ -111,6 +111,34 @@ For example:
|
|
111
111
|
|
112
112
|
For simplicity's sake, the documentation uses the xml module in its examples.
|
113
113
|
|
114
|
+
== Memory Management
|
115
|
+
libxml-ruby automatically manages memory associated with the
|
116
|
+
underlying libxml2 library. There is however one corner case that
|
117
|
+
your code must handle. If a node is imported into a document, but not
|
118
|
+
added to the document, a segmentation fault may occur on program termination.
|
119
|
+
|
120
|
+
# Do NOT do this
|
121
|
+
require 'xml'
|
122
|
+
doc1 = XML::Document.string("test1")
|
123
|
+
doc2 = XML::Document.string("test2")
|
124
|
+
node = doc2.import(doc1.root)
|
125
|
+
|
126
|
+
If doc2 is freed before node2 a segmentatin fault will occur since
|
127
|
+
node2 references the document. To avoid this, simply make sure to add the
|
128
|
+
node to the document:
|
129
|
+
|
130
|
+
# DO this instead
|
131
|
+
doc1 = XML::Document.string("test1")
|
132
|
+
doc2 = XML::Document.string("test2")
|
133
|
+
doc2.root << doc2.import(doc1.root)
|
134
|
+
|
135
|
+
Alternatively, you can call node2.remove! to disassociate node2 from doc2.
|
136
|
+
|
137
|
+
== Threading
|
138
|
+
libxml-ruby fully supports native, background Ruby threads. This of course
|
139
|
+
only applies to Ruby 1.9.x and higher since earlier versions of Ruby do not
|
140
|
+
support native threads.
|
141
|
+
|
114
142
|
== Performance
|
115
143
|
In addition to being feature rich and conformation, the main reason
|
116
144
|
people use libxml-ruby is for performance. Here are the results
|
@@ -134,12 +162,14 @@ From https://svn.concord.org/svn/projects/trunk/common/ruby/xml_benchmarks/
|
|
134
162
|
|
135
163
|
|
136
164
|
== Documentation
|
137
|
-
Documentation is available via rdoc
|
138
|
-
|
139
|
-
|
165
|
+
Documentation is available via rdoc, and is installed automatically with the
|
166
|
+
gem.
|
167
|
+
|
168
|
+
libxml-ruby's online documentation is generated using Hanna. To generate
|
169
|
+
documentation from source:
|
140
170
|
|
141
|
-
gem install
|
142
|
-
rake rdoc
|
171
|
+
gem install hanna
|
172
|
+
rake rdoc
|
143
173
|
|
144
174
|
Note that older versions of Rdoc, which ship with Ruby 1.8.x, will report
|
145
175
|
a number of errors. To avoid them, install Rdoc 2.1 or higher from
|
@@ -152,8 +182,8 @@ ruby/lib/ruby/1.8/rdoc_old.
|
|
152
182
|
|
153
183
|
If you have any questions about using libxml-ruby, please send them to
|
154
184
|
libxml-devel@rubyforge.org. If you have found any bugs in libxml-devel,
|
155
|
-
or have developed new patches, please submit them to
|
156
|
-
|
185
|
+
or have developed new patches, please submit them to Git Hub at
|
186
|
+
https://github.com/xml4r/libxml-ruby/issues.
|
157
187
|
|
158
188
|
== License
|
159
189
|
See LICENSE for license information.
|
data/ext/libxml/ruby_libxml.h
CHANGED
data/ext/libxml/ruby_xml_attr.c
CHANGED
@@ -186,7 +186,7 @@ static VALUE rxml_attr_name_get(VALUE self)
|
|
186
186
|
if (xattr->name == NULL)
|
187
187
|
return Qnil;
|
188
188
|
else
|
189
|
-
return rxml_str_new2((const char*) xattr->name, xattr->doc->encoding);
|
189
|
+
return rxml_str_new2((const char*) xattr->name, (xattr->doc ? xattr->doc->encoding : NULL));
|
190
190
|
}
|
191
191
|
|
192
192
|
/*
|
@@ -302,7 +302,7 @@ VALUE rxml_attr_value_get(VALUE self)
|
|
302
302
|
|
303
303
|
if (value != NULL)
|
304
304
|
{
|
305
|
-
result = rxml_str_new2((const char*) value, xattr->doc->encoding);
|
305
|
+
result = rxml_str_new2((const char*) value, (xattr->doc ? xattr->doc->encoding : NULL));
|
306
306
|
xmlFree(value);
|
307
307
|
}
|
308
308
|
return result;
|
@@ -20,7 +20,7 @@
|
|
20
20
|
* doc = XML::Document.new()
|
21
21
|
* doc.root = XML::Node.new('root_node')
|
22
22
|
* doc.root << XML::Node.new('elem1')
|
23
|
-
* doc.save(filename, :indent => true, :encoding =>
|
23
|
+
* doc.save(filename, :indent => true, :encoding => XML::Encoding::UTF_8)
|
24
24
|
*
|
25
25
|
* To write a document to a file:
|
26
26
|
*
|
@@ -45,7 +45,7 @@
|
|
45
45
|
*
|
46
46
|
* elem3['attr'] = 'baz'
|
47
47
|
*
|
48
|
-
* doc.save(filename, :indent => true, :encoding =>
|
48
|
+
* doc.save(filename, :indent => true, :encoding => XML::Encoding::UTF_8)
|
49
49
|
*/
|
50
50
|
|
51
51
|
#include <stdarg.h>
|
@@ -123,6 +123,40 @@ static VALUE rxml_document_initialize(int argc, VALUE *argv, VALUE self)
|
|
123
123
|
return self;
|
124
124
|
}
|
125
125
|
|
126
|
+
/*
|
127
|
+
* call-seq:
|
128
|
+
* document.canonicalize(comments) -> String
|
129
|
+
*
|
130
|
+
* Returns a string containing the canonicalized form of the document.
|
131
|
+
*
|
132
|
+
* :comments - Specifies if comments should be output. This is an optional
|
133
|
+
* parameter whose default value is false.
|
134
|
+
*/
|
135
|
+
static VALUE rxml_document_canonicalize(int argc, VALUE *argv, VALUE self)
|
136
|
+
{
|
137
|
+
VALUE result = Qnil;
|
138
|
+
VALUE comments = Qnil ;
|
139
|
+
xmlDocPtr xdoc;
|
140
|
+
xmlChar *buffer = NULL;
|
141
|
+
int length;
|
142
|
+
|
143
|
+
rb_scan_args(argc, argv, "01", &comments);
|
144
|
+
|
145
|
+
Data_Get_Struct(self, xmlDoc, xdoc);
|
146
|
+
length = xmlC14NDocDumpMemory(xdoc, NULL, XML_C14N_1_1, NULL,
|
147
|
+
(comments == Qtrue ? 1 : 0),
|
148
|
+
&buffer);
|
149
|
+
|
150
|
+
if (buffer)
|
151
|
+
{
|
152
|
+
result = rxml_str_new2((const char*) buffer, (const char*)xdoc->encoding);
|
153
|
+
xmlFree(buffer);
|
154
|
+
}
|
155
|
+
|
156
|
+
return result;
|
157
|
+
}
|
158
|
+
|
159
|
+
|
126
160
|
/*
|
127
161
|
* call-seq:
|
128
162
|
* document.compression -> num
|
@@ -285,16 +319,17 @@ static VALUE rxml_document_encoding_get(VALUE self)
|
|
285
319
|
* Returns the Ruby encoding specified by this document
|
286
320
|
* (available on Ruby 1.9.x and higher).
|
287
321
|
*/
|
322
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
288
323
|
static VALUE rxml_document_rb_encoding_get(VALUE self)
|
289
324
|
{
|
290
325
|
xmlDocPtr xdoc;
|
291
326
|
const char *xencoding;
|
292
|
-
VALUE encoding;
|
293
327
|
Data_Get_Struct(self, xmlDoc, xdoc);
|
294
328
|
|
295
329
|
xencoding = (const char*)xdoc->encoding;
|
296
330
|
return rxml_xml_encoding_to_rb_encoding(mXMLEncoding, xmlParseCharEncoding(xencoding));
|
297
331
|
}
|
332
|
+
#endif
|
298
333
|
|
299
334
|
/*
|
300
335
|
* call-seq:
|
@@ -322,6 +357,11 @@ static VALUE rxml_document_encoding_set(VALUE self, VALUE encoding)
|
|
322
357
|
*
|
323
358
|
* Creates a copy of the node that can be inserted into the
|
324
359
|
* current document.
|
360
|
+
*
|
361
|
+
* IMPORTANT - The returned node MUST be inserted into the document.
|
362
|
+
* This is because the returned node refereces internal LibXML data
|
363
|
+
* structures owned by the document. Therefore, if the document is
|
364
|
+
* is freed before the the node is freed a segmentation fault will occur.
|
325
365
|
*/
|
326
366
|
static VALUE rxml_document_import(VALUE self, VALUE node)
|
327
367
|
{
|
@@ -534,6 +574,9 @@ static VALUE rxml_document_root_set(VALUE self, VALUE node)
|
|
534
574
|
Data_Get_Struct(self, xmlDoc, xdoc);
|
535
575
|
Data_Get_Struct(node, xmlNode, xnode);
|
536
576
|
|
577
|
+
if (xnode->doc != NULL && xnode->doc != xdoc)
|
578
|
+
rb_raise(eXMLError, "Nodes belong to different documents. You must first import the node by calling XML::Document.import");
|
579
|
+
|
537
580
|
xroot = xmlDocSetRootElement(xdoc, xnode);
|
538
581
|
return node;
|
539
582
|
}
|
@@ -541,7 +584,7 @@ static VALUE rxml_document_root_set(VALUE self, VALUE node)
|
|
541
584
|
/*
|
542
585
|
* call-seq:
|
543
586
|
* document.save(filename) -> int
|
544
|
-
* document.save(filename, :indent => true, :encoding =>
|
587
|
+
* document.save(filename, :indent => true, :encoding => XML::Encoding::UTF_8) -> int
|
545
588
|
*
|
546
589
|
* Saves a document to a file. You may provide an optional hash table
|
547
590
|
* to control how the string is generated. Valid options are:
|
@@ -619,7 +662,7 @@ static VALUE rxml_document_standalone_q(VALUE self)
|
|
619
662
|
/*
|
620
663
|
* call-seq:
|
621
664
|
* document.to_s -> "string"
|
622
|
-
* document.to_s(:indent => true, :encoding =>
|
665
|
+
* document.to_s(:indent => true, :encoding => XML::Encoding::UTF_8) -> "string"
|
623
666
|
*
|
624
667
|
* Converts a document, and all of its children, to a string representation.
|
625
668
|
* You may provide an optional hash table to control how the string is
|
@@ -771,9 +814,11 @@ static VALUE rxml_document_order_elements(VALUE self)
|
|
771
814
|
|
772
815
|
/*
|
773
816
|
* call-seq:
|
774
|
-
* document.validate_schema(schema)
|
817
|
+
* document.validate_schema(schema)
|
775
818
|
*
|
776
819
|
* Validate this document against the specified XML::Schema.
|
820
|
+
* If the document is valid the method returns true. Otherwise an
|
821
|
+
* exception is raised with validation information.
|
777
822
|
*/
|
778
823
|
static VALUE rxml_document_validate_schema(VALUE self, VALUE schema)
|
779
824
|
{
|
@@ -802,9 +847,11 @@ static VALUE rxml_document_validate_schema(VALUE self, VALUE schema)
|
|
802
847
|
|
803
848
|
/*
|
804
849
|
* call-seq:
|
805
|
-
* document.
|
850
|
+
* document.validate_relaxng(relaxng)
|
806
851
|
*
|
807
852
|
* Validate this document against the specified XML::RelaxNG.
|
853
|
+
* If the document is valid the method returns true. Otherwise an
|
854
|
+
* exception is raised with validation information.
|
808
855
|
*/
|
809
856
|
static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng)
|
810
857
|
{
|
@@ -836,6 +883,8 @@ static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng)
|
|
836
883
|
* document.validate(dtd) -> (true|false)
|
837
884
|
*
|
838
885
|
* Validate this document against the specified XML::DTD.
|
886
|
+
* If the document is valid the method returns true. Otherwise an
|
887
|
+
* exception is raised with validation information.
|
839
888
|
*/
|
840
889
|
static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd)
|
841
890
|
{
|
@@ -871,6 +920,7 @@ void rxml_init_document(void)
|
|
871
920
|
rb_define_alloc_func(cXMLDocument, rxml_document_alloc);
|
872
921
|
|
873
922
|
rb_define_method(cXMLDocument, "initialize", rxml_document_initialize, -1);
|
923
|
+
rb_define_method(cXMLDocument, "canonicalize", rxml_document_canonicalize, -1);
|
874
924
|
rb_define_method(cXMLDocument, "child", rxml_document_child_get, 0);
|
875
925
|
rb_define_method(cXMLDocument, "child?", rxml_document_child_q, 0);
|
876
926
|
rb_define_method(cXMLDocument, "compression", rxml_document_compression_get, 0);
|
data/ext/libxml/ruby_xml_error.c
CHANGED
@@ -131,18 +131,6 @@ static void structuredErrorFunc(void *userData, xmlErrorPtr xerror)
|
|
131
131
|
/* Wrap error up as Ruby object and send it off to ruby */
|
132
132
|
VALUE block = rb_cvar_get(eXMLError, ERROR_HANDLER_ID);
|
133
133
|
|
134
|
-
/* This next bit of code is a total hack to get around a bug
|
135
|
-
in libxml which causes error handlers on sax handlers to
|
136
|
-
be ignored in favor of the global handler. In addition,
|
137
|
-
the correct context is also not passed in. So try to
|
138
|
-
dig it out. */
|
139
|
-
if (!userData && xerror->ctxt)
|
140
|
-
{
|
141
|
-
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) xerror->ctxt;
|
142
|
-
if (ctxt != ctxt->userData)
|
143
|
-
userData = ctxt->userData;
|
144
|
-
}
|
145
|
-
|
146
134
|
/* Now call global handler */
|
147
135
|
if (block != Qnil)
|
148
136
|
{
|
data/ext/libxml/ruby_xml_node.c
CHANGED
@@ -33,11 +33,11 @@ VALUE cXMLNode;
|
|
33
33
|
* a libxml document. When a Ruby node is freed, the _private
|
34
34
|
* field is set back to null.
|
35
35
|
*
|
36
|
-
* In the sweep phase in Ruby 1.9
|
37
|
-
* the nodes. To support
|
38
|
-
* function with libxml that is called each time a node
|
39
|
-
* In that case, the data_ptr is set to null, so the bindings
|
40
|
-
* can recognize the
|
36
|
+
* In the sweep phase in Ruby 1.9.*, the document tends to be
|
37
|
+
* freed before the nodes. To support this, the bindings register
|
38
|
+
* a callback function with libxml that is called each time a node
|
39
|
+
* is freed. In that case, the data_ptr is set to null, so the bindings
|
40
|
+
* can recognize the situation.
|
41
41
|
*/
|
42
42
|
|
43
43
|
static void rxml_node_deregisterNode(xmlNodePtr xnode)
|
@@ -50,6 +50,8 @@ static void rxml_node_deregisterNode(xmlNodePtr xnode)
|
|
50
50
|
try to free the node a second time. */
|
51
51
|
VALUE node = (VALUE) xnode->_private;
|
52
52
|
RDATA(node)->data = NULL;
|
53
|
+
RDATA(node)->dfree = NULL;
|
54
|
+
RDATA(node)->dmark = NULL;
|
53
55
|
}
|
54
56
|
}
|
55
57
|
|
@@ -64,40 +66,46 @@ static void rxml_node_free(xmlNodePtr xnode)
|
|
64
66
|
/* The ruby object wrapping the xml object no longer exists. */
|
65
67
|
xnode->_private = NULL;
|
66
68
|
|
67
|
-
/* Ruby is responsible for freeing this node
|
68
|
-
|
69
|
+
/* Ruby is responsible for freeing this node if it does not
|
70
|
+
have a parent and is not owned by a document. Note a corner
|
71
|
+
case here - calling node2 = doc.import(node1) will cause node2
|
72
|
+
to not have a parent but to have a document. */
|
69
73
|
if (xnode->parent == NULL)
|
74
|
+
{
|
70
75
|
xmlFreeNode(xnode);
|
76
|
+
}
|
71
77
|
}
|
72
78
|
|
73
79
|
void rxml_node_mark(xmlNodePtr xnode)
|
74
80
|
{
|
75
|
-
/* Either the node has been created yet in initialize
|
81
|
+
/* Either the node has not been created yet in initialize
|
76
82
|
or it has been freed by libxml already in Ruby's
|
77
83
|
mark phase. */
|
78
84
|
if (xnode == NULL)
|
79
85
|
return;
|
80
86
|
|
81
|
-
if (xnode->doc
|
87
|
+
if (xnode->doc && xnode->doc->_private)
|
82
88
|
rb_gc_mark((VALUE) xnode->doc->_private);
|
83
89
|
|
84
|
-
if (xnode->parent
|
90
|
+
if (xnode->parent && xnode->parent->_private)
|
85
91
|
rb_gc_mark((VALUE) xnode->_private);
|
86
92
|
}
|
87
93
|
|
88
94
|
VALUE rxml_node_wrap(xmlNodePtr xnode)
|
89
95
|
{
|
96
|
+
VALUE result;
|
97
|
+
|
90
98
|
/* Is the node already wrapped? */
|
91
99
|
if (xnode->_private != NULL)
|
92
100
|
{
|
93
|
-
|
101
|
+
result = (VALUE) xnode->_private;
|
94
102
|
}
|
95
103
|
else
|
96
104
|
{
|
97
|
-
|
98
|
-
xnode->_private = (void*)
|
99
|
-
return node;
|
105
|
+
result = Data_Wrap_Struct(cXMLNode, rxml_node_mark, rxml_node_free, xnode);
|
106
|
+
xnode->_private = (void*) result;
|
100
107
|
}
|
108
|
+
return result;
|
101
109
|
}
|
102
110
|
|
103
111
|
static VALUE rxml_node_alloc(VALUE klass)
|
@@ -107,6 +115,17 @@ static VALUE rxml_node_alloc(VALUE klass)
|
|
107
115
|
return Data_Wrap_Struct(klass, rxml_node_mark, rxml_node_free, NULL);
|
108
116
|
}
|
109
117
|
|
118
|
+
static xmlNodePtr rxml_get_xnode(VALUE node)
|
119
|
+
{
|
120
|
+
xmlNodePtr result;
|
121
|
+
Data_Get_Struct(node, xmlNode, result);
|
122
|
+
|
123
|
+
if (!result)
|
124
|
+
rb_raise(rb_eRuntimeError, "This node has already been freed.");
|
125
|
+
|
126
|
+
return result;
|
127
|
+
}
|
128
|
+
|
110
129
|
/*
|
111
130
|
* call-seq:
|
112
131
|
* XML::Node.new_cdata(content = nil) -> XML::Node
|
@@ -237,11 +256,13 @@ static VALUE rxml_node_modify_dom(VALUE self, VALUE target,
|
|
237
256
|
if (rb_obj_is_kind_of(target, cXMLNode) == Qfalse)
|
238
257
|
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
239
258
|
|
240
|
-
|
241
|
-
|
259
|
+
xnode = rxml_get_xnode(self);
|
260
|
+
xtarget = rxml_get_xnode(target);
|
242
261
|
|
243
262
|
if (xtarget->doc != NULL && xtarget->doc != xnode->doc)
|
244
|
-
rb_raise(eXMLError, "Nodes belong to different documents. You must first import the by calling XML::Document.import");
|
263
|
+
rb_raise(eXMLError, "Nodes belong to different documents. You must first import the node by calling XML::Document.import");
|
264
|
+
|
265
|
+
xmlUnlinkNode(xtarget);
|
245
266
|
|
246
267
|
/* This target node could be freed here. */
|
247
268
|
xresult = xmlFunc(xnode, xtarget);
|
@@ -271,7 +292,7 @@ static VALUE rxml_node_base_uri_get(VALUE self)
|
|
271
292
|
xmlChar* base_uri;
|
272
293
|
VALUE result = Qnil;
|
273
294
|
|
274
|
-
|
295
|
+
xnode = rxml_get_xnode(self);
|
275
296
|
|
276
297
|
if (xnode->doc == NULL)
|
277
298
|
return (result);
|
@@ -299,7 +320,7 @@ static VALUE rxml_node_base_uri_set(VALUE self, VALUE uri)
|
|
299
320
|
xmlNodePtr xnode;
|
300
321
|
|
301
322
|
Check_Type(uri, T_STRING);
|
302
|
-
|
323
|
+
xnode = rxml_get_xnode(self);
|
303
324
|
if (xnode->doc == NULL)
|
304
325
|
return (Qnil);
|
305
326
|
|
@@ -319,7 +340,7 @@ static VALUE rxml_node_content_get(VALUE self)
|
|
319
340
|
xmlChar *content;
|
320
341
|
VALUE result = Qnil;
|
321
342
|
|
322
|
-
|
343
|
+
xnode = rxml_get_xnode(self);
|
323
344
|
content = xmlNodeGetContent(xnode);
|
324
345
|
if (content)
|
325
346
|
{
|
@@ -341,7 +362,7 @@ static VALUE rxml_node_content_set(VALUE self, VALUE content)
|
|
341
362
|
xmlNodePtr xnode;
|
342
363
|
|
343
364
|
Check_Type(content, T_STRING);
|
344
|
-
|
365
|
+
xnode = rxml_get_xnode(self);
|
345
366
|
// XXX docs indicate need for escaping entites, need to be done? danj
|
346
367
|
xmlNodeSetContent(xnode, (xmlChar*) StringValuePtr(content));
|
347
368
|
return (Qtrue);
|
@@ -362,7 +383,7 @@ static VALUE rxml_node_content_stripped_get(VALUE self)
|
|
362
383
|
xmlChar* content;
|
363
384
|
VALUE result = Qnil;
|
364
385
|
|
365
|
-
|
386
|
+
xnode = rxml_get_xnode(self);
|
366
387
|
|
367
388
|
if (!xnode->content)
|
368
389
|
return result;
|
@@ -387,7 +408,7 @@ static VALUE rxml_node_debug(VALUE self)
|
|
387
408
|
{
|
388
409
|
#ifdef LIBXML_DEBUG_ENABLED
|
389
410
|
xmlNodePtr xnode;
|
390
|
-
|
411
|
+
xnode = rxml_get_xnode(self);
|
391
412
|
xmlDebugDumpNode(NULL, xnode, 2);
|
392
413
|
return Qtrue;
|
393
414
|
#else
|
@@ -406,7 +427,7 @@ static VALUE rxml_node_first_get(VALUE self)
|
|
406
427
|
{
|
407
428
|
xmlNodePtr xnode;
|
408
429
|
|
409
|
-
|
430
|
+
xnode = rxml_get_xnode(self);
|
410
431
|
|
411
432
|
if (xnode->children)
|
412
433
|
return (rxml_node_wrap(xnode->children));
|
@@ -434,16 +455,14 @@ static VALUE rxml_node_content_add(VALUE self, VALUE obj)
|
|
434
455
|
xmlNodePtr xnode;
|
435
456
|
VALUE str;
|
436
457
|
|
437
|
-
|
458
|
+
xnode = rxml_get_xnode(self);
|
459
|
+
|
438
460
|
/* XXX This should only be legal for a CDATA type node, I think,
|
439
461
|
* resulting in a merge of content, as if a string were passed
|
440
462
|
* danj 070827
|
441
463
|
*/
|
442
464
|
if (rb_obj_is_kind_of(obj, cXMLNode))
|
443
465
|
{
|
444
|
-
xmlNodePtr xtarget;
|
445
|
-
Data_Get_Struct(obj, xmlNode, xtarget);
|
446
|
-
xmlUnlinkNode(xtarget);
|
447
466
|
rxml_node_modify_dom(self, obj, xmlAddChild);
|
448
467
|
}
|
449
468
|
else
|
@@ -465,41 +484,32 @@ static VALUE rxml_node_content_add(VALUE self, VALUE obj)
|
|
465
484
|
*/
|
466
485
|
static VALUE rxml_node_doc(VALUE self)
|
467
486
|
{
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
Data_Get_Struct(self, xmlNode, xnode);
|
487
|
+
xmlDocPtr xdoc = NULL;
|
488
|
+
xmlNodePtr xnode = rxml_get_xnode(self);
|
472
489
|
|
473
490
|
switch (xnode->type)
|
474
491
|
{
|
475
492
|
case XML_DOCUMENT_NODE:
|
476
493
|
#ifdef LIBXML_DOCB_ENABLED
|
477
|
-
|
494
|
+
case XML_DOCB_DOCUMENT_NODE:
|
478
495
|
#endif
|
479
496
|
case XML_HTML_DOCUMENT_NODE:
|
480
|
-
|
497
|
+
case XML_NAMESPACE_DECL:
|
481
498
|
break;
|
482
499
|
case XML_ATTRIBUTE_NODE:
|
483
|
-
|
484
|
-
xmlAttrPtr attr = (xmlAttrPtr) xnode;
|
485
|
-
doc = attr->doc;
|
486
|
-
break;
|
487
|
-
}
|
488
|
-
case XML_NAMESPACE_DECL:
|
489
|
-
doc = NULL;
|
500
|
+
xdoc = (xmlDocPtr)((xmlAttrPtr) xnode->doc);
|
490
501
|
break;
|
491
502
|
default:
|
492
|
-
|
493
|
-
break;
|
503
|
+
xdoc = xnode->doc;
|
494
504
|
}
|
495
505
|
|
496
|
-
if (
|
506
|
+
if (xdoc == NULL)
|
497
507
|
return (Qnil);
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
508
|
+
else if (xdoc->_private)
|
509
|
+
return (VALUE) xdoc->_private;
|
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?)");
|
503
513
|
}
|
504
514
|
|
505
515
|
/*
|
@@ -567,7 +577,8 @@ static VALUE rxml_node_to_s(int argc, VALUE *argv, VALUE self)
|
|
567
577
|
encodingHandler = xmlFindCharEncodingHandler(xencoding);
|
568
578
|
output = xmlAllocOutputBuffer(encodingHandler);
|
569
579
|
|
570
|
-
|
580
|
+
xnode = rxml_get_xnode(self);
|
581
|
+
|
571
582
|
xmlNodeDumpOutput(output, xnode->doc, xnode, level, indent, xencoding);
|
572
583
|
xmlOutputBufferFlush(output);
|
573
584
|
|
@@ -597,7 +608,7 @@ static VALUE rxml_node_each(VALUE self)
|
|
597
608
|
{
|
598
609
|
xmlNodePtr xnode;
|
599
610
|
xmlNodePtr xcurrent;
|
600
|
-
|
611
|
+
xnode = rxml_get_xnode(self);
|
601
612
|
|
602
613
|
xcurrent = xnode->children;
|
603
614
|
|
@@ -617,12 +628,12 @@ static VALUE rxml_node_each(VALUE self)
|
|
617
628
|
* call-seq:
|
618
629
|
* node.empty? -> (true|false)
|
619
630
|
*
|
620
|
-
* Determine whether this node is empty.
|
631
|
+
* Determine whether this node is an empty or whitespace only text-node.
|
621
632
|
*/
|
622
633
|
static VALUE rxml_node_empty_q(VALUE self)
|
623
634
|
{
|
624
635
|
xmlNodePtr xnode;
|
625
|
-
|
636
|
+
xnode = rxml_get_xnode(self);
|
626
637
|
if (xnode == NULL)
|
627
638
|
return (Qnil);
|
628
639
|
|
@@ -638,26 +649,26 @@ static VALUE rxml_node_empty_q(VALUE self)
|
|
638
649
|
* if they are the same node or have the same XML representation.*/
|
639
650
|
static VALUE rxml_node_eql_q(VALUE self, VALUE other)
|
640
651
|
{
|
641
|
-
if(self == other)
|
642
|
-
{
|
643
|
-
|
644
|
-
}
|
645
|
-
else if (NIL_P(other))
|
646
|
-
{
|
647
|
-
|
648
|
-
}
|
649
|
-
else
|
650
|
-
{
|
651
|
-
|
652
|
-
|
652
|
+
if(self == other)
|
653
|
+
{
|
654
|
+
return Qtrue;
|
655
|
+
}
|
656
|
+
else if (NIL_P(other))
|
657
|
+
{
|
658
|
+
return Qfalse;
|
659
|
+
}
|
660
|
+
else
|
661
|
+
{
|
662
|
+
VALUE self_xml;
|
663
|
+
VALUE other_xml;
|
653
664
|
|
654
|
-
|
655
|
-
|
665
|
+
if (rb_obj_is_kind_of(other, cXMLNode) == Qfalse)
|
666
|
+
rb_raise(rb_eTypeError, "Nodes can only be compared against other nodes");
|
656
667
|
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
}
|
668
|
+
self_xml = rxml_node_to_s(0, NULL, self);
|
669
|
+
other_xml = rxml_node_to_s(0, NULL, other);
|
670
|
+
return(rb_funcall(self_xml, rb_intern("=="), 1, other_xml));
|
671
|
+
}
|
661
672
|
}
|
662
673
|
|
663
674
|
/*
|
@@ -673,7 +684,7 @@ static VALUE rxml_node_lang_get(VALUE self)
|
|
673
684
|
xmlChar *lang;
|
674
685
|
VALUE result = Qnil;
|
675
686
|
|
676
|
-
|
687
|
+
xnode = rxml_get_xnode(self);
|
677
688
|
lang = xmlNodeGetLang(xnode);
|
678
689
|
|
679
690
|
if (lang)
|
@@ -699,7 +710,7 @@ static VALUE rxml_node_lang_set(VALUE self, VALUE lang)
|
|
699
710
|
xmlNodePtr xnode;
|
700
711
|
|
701
712
|
Check_Type(lang, T_STRING);
|
702
|
-
|
713
|
+
xnode = rxml_get_xnode(self);
|
703
714
|
xmlNodeSetLang(xnode, (xmlChar*) StringValuePtr(lang));
|
704
715
|
|
705
716
|
return (Qtrue);
|
@@ -715,7 +726,7 @@ static VALUE rxml_node_last_get(VALUE self)
|
|
715
726
|
{
|
716
727
|
xmlNodePtr xnode;
|
717
728
|
|
718
|
-
|
729
|
+
xnode = rxml_get_xnode(self);
|
719
730
|
|
720
731
|
if (xnode->last)
|
721
732
|
return (rxml_node_wrap(xnode->last));
|
@@ -735,7 +746,7 @@ static VALUE rxml_node_line_num(VALUE self)
|
|
735
746
|
{
|
736
747
|
xmlNodePtr xnode;
|
737
748
|
long line_num;
|
738
|
-
|
749
|
+
xnode = rxml_get_xnode(self);
|
739
750
|
|
740
751
|
if (!xmlLineNumbersDefaultValue)
|
741
752
|
rb_warn(
|
@@ -759,7 +770,7 @@ static VALUE rxml_node_xlink_q(VALUE self)
|
|
759
770
|
xmlNodePtr xnode;
|
760
771
|
xlinkType xlt;
|
761
772
|
|
762
|
-
|
773
|
+
xnode = rxml_get_xnode(self);
|
763
774
|
xlt = xlinkIsLink(xnode->doc, xnode);
|
764
775
|
|
765
776
|
if (xlt == XLINK_TYPE_NONE)
|
@@ -781,7 +792,7 @@ static VALUE rxml_node_xlink_type(VALUE self)
|
|
781
792
|
xmlNodePtr xnode;
|
782
793
|
xlinkType xlt;
|
783
794
|
|
784
|
-
|
795
|
+
xnode = rxml_get_xnode(self);
|
785
796
|
xlt = xlinkIsLink(xnode->doc, xnode);
|
786
797
|
|
787
798
|
if (xlt == XLINK_TYPE_NONE)
|
@@ -803,7 +814,7 @@ static VALUE rxml_node_xlink_type_name(VALUE self)
|
|
803
814
|
xmlNodePtr xnode;
|
804
815
|
xlinkType xlt;
|
805
816
|
|
806
|
-
|
817
|
+
xnode = rxml_get_xnode(self);
|
807
818
|
xlt = xlinkIsLink(xnode->doc, xnode);
|
808
819
|
|
809
820
|
switch (xlt)
|
@@ -832,7 +843,7 @@ static VALUE rxml_node_name_get(VALUE self)
|
|
832
843
|
xmlNodePtr xnode;
|
833
844
|
const xmlChar *name;
|
834
845
|
|
835
|
-
|
846
|
+
xnode = rxml_get_xnode(self);
|
836
847
|
|
837
848
|
switch (xnode->type)
|
838
849
|
{
|
@@ -881,7 +892,7 @@ static VALUE rxml_node_name_set(VALUE self, VALUE name)
|
|
881
892
|
const xmlChar *xname;
|
882
893
|
|
883
894
|
Check_Type(name, T_STRING);
|
884
|
-
|
895
|
+
xnode = rxml_get_xnode(self);
|
885
896
|
xname = (const xmlChar*)StringValuePtr(name);
|
886
897
|
|
887
898
|
/* Note: calling xmlNodeSetName() for a text node is ignored by libXML. */
|
@@ -900,7 +911,7 @@ static VALUE rxml_node_next_get(VALUE self)
|
|
900
911
|
{
|
901
912
|
xmlNodePtr xnode;
|
902
913
|
|
903
|
-
|
914
|
+
xnode = rxml_get_xnode(self);
|
904
915
|
|
905
916
|
if (xnode->next)
|
906
917
|
return (rxml_node_wrap(xnode->next));
|
@@ -933,7 +944,7 @@ static VALUE rxml_node_parent_get(VALUE self)
|
|
933
944
|
{
|
934
945
|
xmlNodePtr xnode;
|
935
946
|
|
936
|
-
|
947
|
+
xnode = rxml_get_xnode(self);
|
937
948
|
|
938
949
|
if (xnode->parent)
|
939
950
|
return (rxml_node_wrap(xnode->parent));
|
@@ -952,7 +963,7 @@ static VALUE rxml_node_path(VALUE self)
|
|
952
963
|
xmlNodePtr xnode;
|
953
964
|
xmlChar *path;
|
954
965
|
|
955
|
-
|
966
|
+
xnode = rxml_get_xnode(self);
|
956
967
|
path = xmlGetNodePath(xnode);
|
957
968
|
|
958
969
|
if (path == NULL)
|
@@ -982,7 +993,7 @@ static VALUE rxml_node_prev_get(VALUE self)
|
|
982
993
|
{
|
983
994
|
xmlNodePtr xnode;
|
984
995
|
xmlNodePtr node;
|
985
|
-
|
996
|
+
xnode = rxml_get_xnode(self);
|
986
997
|
|
987
998
|
switch (xnode->type)
|
988
999
|
{
|
@@ -1036,7 +1047,7 @@ static VALUE rxml_node_attributes_get(VALUE self)
|
|
1036
1047
|
{
|
1037
1048
|
xmlNodePtr xnode;
|
1038
1049
|
|
1039
|
-
|
1050
|
+
xnode = rxml_get_xnode(self);
|
1040
1051
|
return rxml_attributes_new(xnode);
|
1041
1052
|
}
|
1042
1053
|
|
@@ -1077,7 +1088,7 @@ static VALUE rxml_node_property_set(VALUE self, VALUE name, VALUE value)
|
|
1077
1088
|
static VALUE rxml_node_remove_ex(VALUE self)
|
1078
1089
|
{
|
1079
1090
|
xmlNodePtr xnode, xresult;
|
1080
|
-
|
1091
|
+
xnode = rxml_get_xnode(self);
|
1081
1092
|
|
1082
1093
|
/* First unlink the node from its parent. */
|
1083
1094
|
xmlUnlinkNode(xnode);
|
@@ -1137,7 +1148,7 @@ static VALUE rxml_node_sibling_set(VALUE self, VALUE sibling)
|
|
1137
1148
|
static VALUE rxml_node_output_escaping_q(VALUE self)
|
1138
1149
|
{
|
1139
1150
|
xmlNodePtr xnode;
|
1140
|
-
|
1151
|
+
xnode = rxml_get_xnode(self);
|
1141
1152
|
|
1142
1153
|
switch (xnode->type) {
|
1143
1154
|
case XML_TEXT_NODE:
|
@@ -1184,7 +1195,7 @@ static VALUE rxml_node_output_escaping_q(VALUE self)
|
|
1184
1195
|
static VALUE rxml_node_output_escaping_set(VALUE self, VALUE bool)
|
1185
1196
|
{
|
1186
1197
|
xmlNodePtr xnode;
|
1187
|
-
|
1198
|
+
xnode = rxml_get_xnode(self);
|
1188
1199
|
|
1189
1200
|
switch (xnode->type) {
|
1190
1201
|
case XML_TEXT_NODE:
|
@@ -1217,7 +1228,7 @@ static VALUE rxml_node_space_preserve_get(VALUE self)
|
|
1217
1228
|
{
|
1218
1229
|
xmlNodePtr xnode;
|
1219
1230
|
|
1220
|
-
|
1231
|
+
xnode = rxml_get_xnode(self);
|
1221
1232
|
return (INT2NUM(xmlNodeGetSpacePreserve(xnode)));
|
1222
1233
|
}
|
1223
1234
|
|
@@ -1230,7 +1241,7 @@ static VALUE rxml_node_space_preserve_get(VALUE self)
|
|
1230
1241
|
static VALUE rxml_node_space_preserve_set(VALUE self, VALUE bool)
|
1231
1242
|
{
|
1232
1243
|
xmlNodePtr xnode;
|
1233
|
-
|
1244
|
+
xnode = rxml_get_xnode(self);
|
1234
1245
|
|
1235
1246
|
if (TYPE(bool) == T_FALSE)
|
1236
1247
|
xmlNodeSetSpacePreserve(xnode, 0);
|
@@ -1249,7 +1260,7 @@ static VALUE rxml_node_space_preserve_set(VALUE self, VALUE bool)
|
|
1249
1260
|
static VALUE rxml_node_type(VALUE self)
|
1250
1261
|
{
|
1251
1262
|
xmlNodePtr xnode;
|
1252
|
-
|
1263
|
+
xnode = rxml_get_xnode(self);
|
1253
1264
|
return (INT2NUM(xnode->type));
|
1254
1265
|
}
|
1255
1266
|
|
@@ -1268,7 +1279,7 @@ static VALUE rxml_node_copy(VALUE self, VALUE deep)
|
|
1268
1279
|
xmlNodePtr xnode;
|
1269
1280
|
xmlNodePtr xcopy;
|
1270
1281
|
int recursive = (deep == Qnil || deep == Qfalse) ? 0 : 1;
|
1271
|
-
|
1282
|
+
xnode = rxml_get_xnode(self);
|
1272
1283
|
|
1273
1284
|
xcopy = xmlCopyNode(xnode, recursive);
|
1274
1285
|
|
@@ -1280,8 +1291,12 @@ static VALUE rxml_node_copy(VALUE self, VALUE deep)
|
|
1280
1291
|
|
1281
1292
|
void rxml_init_node(void)
|
1282
1293
|
{
|
1294
|
+
/* Register callback for main thread */
|
1283
1295
|
xmlDeregisterNodeDefault(rxml_node_deregisterNode);
|
1284
1296
|
|
1297
|
+
/* Register callback for all other threads */
|
1298
|
+
xmlThrDefDeregisterNodeDefault(rxml_node_deregisterNode);
|
1299
|
+
|
1285
1300
|
cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
|
1286
1301
|
|
1287
1302
|
rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
|