libxml-ruby 2.0.2-x86-mingw32 → 2.0.3-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 +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));
|