libxml-ruby 1.1.2-x86-mswin32-60 → 1.1.3-x86-mswin32-60
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/CHANGES +20 -0
- data/ext/libxml/build.log +4 -4
- data/ext/libxml/extconf.rb +278 -278
- data/ext/libxml/libxml.c +77 -77
- data/ext/libxml/ruby_xml.c +80 -42
- data/ext/libxml/ruby_xml.h +1 -0
- data/ext/libxml/ruby_xml_attr.c +352 -352
- data/ext/libxml/ruby_xml_attr_decl.c +1 -1
- data/ext/libxml/ruby_xml_attributes.c +3 -3
- data/ext/libxml/ruby_xml_cbg.c +86 -86
- data/ext/libxml/ruby_xml_document.c +936 -915
- data/ext/libxml/ruby_xml_dtd.c +1 -1
- data/ext/libxml/ruby_xml_error.c +5 -4
- data/ext/libxml/ruby_xml_html_parser_context.c +18 -0
- data/ext/libxml/ruby_xml_node.c +131 -177
- data/ext/libxml/ruby_xml_node.h +2 -3
- data/ext/libxml/ruby_xml_parser_context.c +32 -2
- data/ext/libxml/ruby_xml_version.h +3 -3
- data/ext/mingw/libxml_ruby.dll.a +0 -0
- data/ext/mingw/libxml_ruby.so +0 -0
- data/lib/libxml/node.rb +11 -0
- data/test/tc_document.rb +13 -2
- data/test/tc_dtd.rb +5 -4
- data/test/tc_node.rb +1 -1
- data/test/tc_node_edit.rb +28 -4
- data/test/tc_xml.rb +12 -0
- data/test/tc_xpath.rb +0 -10
- metadata +2 -3
- data/test/cro_events.html +0 -740
data/ext/libxml/ruby_xml_dtd.c
CHANGED
data/ext/libxml/ruby_xml_error.c
CHANGED
@@ -81,6 +81,7 @@ static VALUE rxml_error_reset_handler(VALUE self)
|
|
81
81
|
VALUE rxml_error_wrap(xmlErrorPtr xerror)
|
82
82
|
{
|
83
83
|
VALUE result = Qnil;
|
84
|
+
|
84
85
|
if (xerror->message)
|
85
86
|
result = rb_exc_new2(eXMLError, xerror->message);
|
86
87
|
else
|
@@ -171,6 +172,10 @@ void rxml_raise(xmlErrorPtr xerror)
|
|
171
172
|
|
172
173
|
void rxml_init_error()
|
173
174
|
{
|
175
|
+
ON_ERROR_METHOD = rb_intern("on_error");
|
176
|
+
CALL_METHOD = rb_intern("call");
|
177
|
+
ERROR_HANDLER_ID = rb_intern("@@__error_handler_callback__");
|
178
|
+
|
174
179
|
/* Intercept libxml error handlers */
|
175
180
|
xmlSetStructuredErrorFunc(NULL, structuredErrorFunc);
|
176
181
|
|
@@ -179,11 +184,7 @@ void rxml_init_error()
|
|
179
184
|
rb_define_singleton_method(eXMLError, "set_handler", rxml_error_set_handler, 0);
|
180
185
|
rb_define_singleton_method(eXMLError, "reset_handler", rxml_error_reset_handler, 0);
|
181
186
|
|
182
|
-
ON_ERROR_METHOD = rb_intern("on_error");
|
183
|
-
CALL_METHOD = rb_intern("call");
|
184
|
-
|
185
187
|
/* Ruby callback to receive errors - set it to nil by default. */
|
186
|
-
ERROR_HANDLER_ID = rb_intern("@@__error_handler_callback__");
|
187
188
|
rxml_set_handler(eXMLError, Qnil);
|
188
189
|
|
189
190
|
/* Error attributes */
|
@@ -155,6 +155,12 @@ static VALUE rxml_html_parser_context_file(VALUE klass, VALUE file)
|
|
155
155
|
if (!ctxt)
|
156
156
|
rxml_raise(&xmlLastError);
|
157
157
|
|
158
|
+
/* This is annoying, but xmlInitParserCtxt (called indirectly above) and
|
159
|
+
xmlCtxtUseOptionsInternal (called below) initialize slightly different
|
160
|
+
context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
|
161
|
+
sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
|
162
|
+
htmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
|
163
|
+
|
158
164
|
return rxml_html_parser_context_wrap(ctxt);
|
159
165
|
}
|
160
166
|
|
@@ -187,6 +193,12 @@ static VALUE rxml_html_parser_context_io(VALUE klass, VALUE io)
|
|
187
193
|
rxml_raise(&xmlLastError);
|
188
194
|
}
|
189
195
|
|
196
|
+
/* This is annoying, but xmlInitParserCtxt (called indirectly above) and
|
197
|
+
xmlCtxtUseOptionsInternal (called below) initialize slightly different
|
198
|
+
context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
|
199
|
+
sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
|
200
|
+
htmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
|
201
|
+
|
190
202
|
stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
|
191
203
|
|
192
204
|
if (!stream)
|
@@ -226,6 +238,12 @@ static VALUE rxml_html_parser_context_string(VALUE klass, VALUE string)
|
|
226
238
|
if (!ctxt)
|
227
239
|
rxml_raise(&xmlLastError);
|
228
240
|
|
241
|
+
/* This is annoying, but xmlInitParserCtxt (called indirectly above) and
|
242
|
+
xmlCtxtUseOptionsInternal (called below) initialize slightly different
|
243
|
+
context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
|
244
|
+
sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
|
245
|
+
htmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
|
246
|
+
|
229
247
|
htmlDefaultSAXHandlerInit();
|
230
248
|
if (ctxt->sax != NULL)
|
231
249
|
memcpy(ctxt->sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1));
|
data/ext/libxml/ruby_xml_node.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "ruby_libxml.h"
|
2
2
|
#include "ruby_xml_node.h"
|
3
|
+
#include <assert.h>
|
3
4
|
|
4
5
|
VALUE cXMLNode;
|
5
6
|
|
@@ -13,18 +14,6 @@ VALUE cXMLNode;
|
|
13
14
|
* documented in the DOM Level 3 specification found at:
|
14
15
|
* http://www.w3.org/TR/DOM-Level-3-Core/. */
|
15
16
|
|
16
|
-
static VALUE rxml_node_content_set(VALUE self, VALUE content);
|
17
|
-
|
18
|
-
VALUE check_string_or_symbol(VALUE val)
|
19
|
-
{
|
20
|
-
if (TYPE(val) != T_STRING && TYPE(val) != T_SYMBOL)
|
21
|
-
{
|
22
|
-
rb_raise(rb_eTypeError,
|
23
|
-
"wrong argument type %s (expected String or Symbol)", rb_obj_classname(
|
24
|
-
val));
|
25
|
-
}
|
26
|
-
return rb_obj_as_string(val);
|
27
|
-
}
|
28
17
|
|
29
18
|
/* Memory management:
|
30
19
|
*
|
@@ -40,13 +29,18 @@ VALUE check_string_or_symbol(VALUE val)
|
|
40
29
|
* * Using the mark function to keep alive any top level, free
|
41
30
|
* standing nodes Ruby is referencing via the node or its children.
|
42
31
|
*
|
43
|
-
*
|
44
|
-
*
|
45
|
-
*
|
46
|
-
*
|
32
|
+
* In general use, this will cause Ruby nodes to be freed before
|
33
|
+
* a libxml document. When a Ruby node is freed, the _private
|
34
|
+
* field is set back to null.
|
35
|
+
*
|
36
|
+
* In the sweep phase in Ruby 1.9.1, the document is freed before
|
37
|
+
* the nodes. To support that, the bindingds register a callback
|
38
|
+
* function with libxml that is called each time a node is freed.
|
39
|
+
* In that case, the data_ptr is set to null, so the bindings
|
40
|
+
* can recognize the situtation.
|
47
41
|
*/
|
48
42
|
|
49
|
-
void rxml_node_deregisterNode(xmlNodePtr xnode)
|
43
|
+
static void rxml_node_deregisterNode(xmlNodePtr xnode)
|
50
44
|
{
|
51
45
|
/* Has the node been wrapped and exposed to Ruby? */
|
52
46
|
if (xnode->_private)
|
@@ -55,59 +49,40 @@ void rxml_node_deregisterNode(xmlNodePtr xnode)
|
|
55
49
|
then dislabe the dfree function so that Ruby will not
|
56
50
|
try to free the node a second time. */
|
57
51
|
VALUE node = (VALUE) xnode->_private;
|
58
|
-
RDATA(node)->
|
59
|
-
RDATA(node)->dfree = NULL;
|
60
|
-
xnode->_private = NULL;
|
52
|
+
RDATA(node)->data = NULL;
|
61
53
|
}
|
62
54
|
}
|
63
55
|
|
64
|
-
void rxml_node_free(xmlNodePtr xnode)
|
56
|
+
static void rxml_node_free(xmlNodePtr xnode)
|
65
57
|
{
|
66
|
-
/*
|
58
|
+
/* Either the node has been created yet in initialize
|
59
|
+
or it has been freed by libxml already in Ruby's
|
60
|
+
mark phase. */
|
61
|
+
if (xnode == NULL)
|
62
|
+
return;
|
63
|
+
|
64
|
+
/* The ruby object wrapping the xml object no longer exists. */
|
67
65
|
xnode->_private = NULL;
|
68
66
|
|
69
|
-
/*
|
70
|
-
|
71
|
-
|
72
|
-
if (xnode->doc == NULL && xnode->parent == NULL)
|
67
|
+
/* Ruby is responsible for freeing this node since it
|
68
|
+
has no parent. */
|
69
|
+
if (xnode->parent == NULL)
|
73
70
|
xmlFreeNode(xnode);
|
74
71
|
}
|
75
72
|
|
76
|
-
void
|
73
|
+
void rxml_node_mark(xmlNodePtr xnode)
|
77
74
|
{
|
78
|
-
|
75
|
+
/* Either the node has been created yet in initialize
|
76
|
+
or it has been freed by libxml already in Ruby's
|
77
|
+
mark phase. */
|
78
|
+
if (xnode == NULL)
|
79
79
|
return;
|
80
80
|
|
81
81
|
if (xnode->doc != NULL)
|
82
|
-
{
|
83
|
-
if (xnode->doc->_private == NULL)
|
84
|
-
rb_bug("XmlNode Doc is not bound! (%s:%d)", __FILE__,__LINE__);
|
85
82
|
rb_gc_mark((VALUE) xnode->doc->_private);
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
while (xnode->parent != NULL)
|
90
|
-
xnode = xnode->parent;
|
91
|
-
|
92
|
-
if (xnode->_private == NULL)
|
93
|
-
rb_warning("XmlNode Root Parent is not bound! (%s:%d)", __FILE__,__LINE__);
|
94
|
-
else
|
95
|
-
rb_gc_mark((VALUE) xnode->_private);
|
96
|
-
}
|
97
|
-
}
|
98
|
-
|
99
|
-
void rxml_node_mark(xmlNodePtr xnode)
|
100
|
-
{
|
101
|
-
if (xnode == NULL)
|
102
|
-
return;
|
103
|
-
|
104
|
-
if (xnode->_private == NULL)
|
105
|
-
{
|
106
|
-
rb_warning("XmlNode is not bound! (%s:%d)", __FILE__, __LINE__);
|
107
|
-
return;
|
108
|
-
}
|
109
|
-
|
110
|
-
rxml_node_mark_common(xnode);
|
83
|
+
|
84
|
+
if (xnode->parent != NULL)
|
85
|
+
rb_gc_mark((VALUE) xnode->_private);
|
111
86
|
}
|
112
87
|
|
113
88
|
VALUE rxml_node_wrap(xmlNodePtr xnode)
|
@@ -119,9 +94,6 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
|
|
119
94
|
}
|
120
95
|
else
|
121
96
|
{
|
122
|
-
/* Assume Ruby is responsible for freeing this node. If libxml frees it
|
123
|
-
instead, the rxml_node_deregisterNode callback is executed, and
|
124
|
-
we set the free function to NULL. */
|
125
97
|
VALUE node = Data_Wrap_Struct(cXMLNode, rxml_node_mark, rxml_node_free, xnode);
|
126
98
|
xnode->_private = (void*) node;
|
127
99
|
return node;
|
@@ -130,7 +102,8 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
|
|
130
102
|
|
131
103
|
static VALUE rxml_node_alloc(VALUE klass)
|
132
104
|
{
|
133
|
-
/* Ruby is responsible for freeing this node not libxml
|
105
|
+
/* Ruby is responsible for freeing this node not libxml but don't set
|
106
|
+
up mark and free yet until we assign the node. */
|
134
107
|
return Data_Wrap_Struct(klass, rxml_node_mark, rxml_node_free, NULL);
|
135
108
|
}
|
136
109
|
|
@@ -217,6 +190,8 @@ static VALUE rxml_node_new_text(VALUE klass, VALUE content)
|
|
217
190
|
return rxml_node_wrap(xnode);
|
218
191
|
}
|
219
192
|
|
193
|
+
static VALUE rxml_node_content_set(VALUE self, VALUE content);
|
194
|
+
|
220
195
|
/*
|
221
196
|
* call-seq:
|
222
197
|
* XML::Node.initialize(name, content = nil, namespace = nil) -> XML::Node
|
@@ -234,14 +209,19 @@ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
|
|
234
209
|
|
235
210
|
rb_scan_args(argc, argv, "12", &name, &content, &ns);
|
236
211
|
|
237
|
-
name =
|
212
|
+
name = rb_obj_as_string(name);
|
238
213
|
|
239
214
|
if (!NIL_P(ns))
|
240
215
|
Data_Get_Struct(ns, xmlNs, xns);
|
241
216
|
|
242
217
|
xnode = xmlNewNode(xns, (xmlChar*) StringValuePtr(name));
|
218
|
+
|
219
|
+
if (xnode == NULL)
|
220
|
+
rxml_raise(&xmlLastError);
|
221
|
+
|
222
|
+
/* Link the Ruby object to the libxml object and vice-versa. */
|
243
223
|
xnode->_private = (void*) self;
|
244
|
-
DATA_PTR(
|
224
|
+
DATA_PTR(self) = xnode;
|
245
225
|
|
246
226
|
if (!NIL_P(content))
|
247
227
|
rxml_node_content_set(self, content);
|
@@ -249,6 +229,36 @@ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
|
|
249
229
|
return self;
|
250
230
|
}
|
251
231
|
|
232
|
+
static VALUE rxml_node_modify_dom(VALUE self, VALUE target,
|
233
|
+
xmlNodePtr (*xmlFunc)(xmlNodePtr, xmlNodePtr))
|
234
|
+
{
|
235
|
+
xmlNodePtr xnode, xtarget, xresult;
|
236
|
+
|
237
|
+
if (rb_obj_is_kind_of(target, cXMLNode) == Qfalse)
|
238
|
+
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
239
|
+
|
240
|
+
Data_Get_Struct(self, xmlNode, xnode);
|
241
|
+
Data_Get_Struct(target, xmlNode, xtarget);
|
242
|
+
|
243
|
+
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");
|
245
|
+
|
246
|
+
/* This target node could be freed here. */
|
247
|
+
xresult = xmlFunc(xnode, xtarget);
|
248
|
+
|
249
|
+
if (!xresult)
|
250
|
+
rxml_raise(&xmlLastError);
|
251
|
+
|
252
|
+
/* Was the target freed? If yes, then wrap the new node */
|
253
|
+
if (xresult != xtarget)
|
254
|
+
{
|
255
|
+
RDATA(target)->data = xresult;
|
256
|
+
xresult->_private = (void*) target;
|
257
|
+
}
|
258
|
+
|
259
|
+
return target;
|
260
|
+
}
|
261
|
+
|
252
262
|
/*
|
253
263
|
* call-seq:
|
254
264
|
* node.base_uri -> "uri"
|
@@ -404,51 +414,20 @@ static VALUE rxml_node_first_get(VALUE self)
|
|
404
414
|
return (Qnil);
|
405
415
|
}
|
406
416
|
|
407
|
-
/*
|
408
|
-
* underlying for child_set and child_add, difference being
|
409
|
-
* former raises on implicit copy, latter does not.
|
410
|
-
*/
|
411
|
-
static VALUE rxml_node_child_set_aux(VALUE self, VALUE child)
|
412
|
-
{
|
413
|
-
xmlNodePtr xnode, xchild, xresult;
|
414
|
-
|
415
|
-
if (rb_obj_is_kind_of(child, cXMLNode) == Qfalse)
|
416
|
-
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
417
|
-
|
418
|
-
Data_Get_Struct(self, xmlNode, xnode);
|
419
|
-
Data_Get_Struct(child, xmlNode, xchild);
|
420
|
-
|
421
|
-
if (xchild->parent != NULL || xchild->doc != NULL)
|
422
|
-
rb_raise(rb_eRuntimeError,
|
423
|
-
"Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
|
424
|
-
|
425
|
-
xresult = xmlAddChild(xnode, xchild);
|
426
|
-
|
427
|
-
if (!xresult)
|
428
|
-
rxml_raise(&xmlLastError);
|
429
|
-
|
430
|
-
return rxml_node_wrap(xresult);
|
431
|
-
}
|
432
417
|
|
433
418
|
/*
|
434
419
|
* call-seq:
|
435
|
-
*
|
420
|
+
* curr_node << "<p>A paragraph</p>"
|
421
|
+
* curr_node << node
|
436
422
|
*
|
437
|
-
*
|
438
|
-
|
439
|
-
static VALUE rxml_node_child_set(VALUE self, VALUE rnode)
|
440
|
-
{
|
441
|
-
return rxml_node_child_set_aux(self, rnode);
|
442
|
-
}
|
443
|
-
|
444
|
-
/*
|
445
|
-
* call-seq:
|
446
|
-
* node << ("string" | node) -> XML::Node
|
423
|
+
* Add the specified text or XML::Node as a new child node to the
|
424
|
+
* current node.
|
447
425
|
*
|
448
|
-
*
|
449
|
-
*
|
450
|
-
*
|
451
|
-
*
|
426
|
+
* If the specified argument is a string, it should be a raw string
|
427
|
+
* that contains unescaped XML special characters. Entity references
|
428
|
+
* are not supported.
|
429
|
+
*
|
430
|
+
* The method will return the current node.
|
452
431
|
*/
|
453
432
|
static VALUE rxml_node_content_add(VALUE self, VALUE obj)
|
454
433
|
{
|
@@ -461,8 +440,11 @@ static VALUE rxml_node_content_add(VALUE self, VALUE obj)
|
|
461
440
|
* danj 070827
|
462
441
|
*/
|
463
442
|
if (rb_obj_is_kind_of(obj, cXMLNode))
|
464
|
-
{
|
465
|
-
|
443
|
+
{
|
444
|
+
xmlNodePtr xtarget;
|
445
|
+
Data_Get_Struct(obj, xmlNode, xtarget);
|
446
|
+
xmlUnlinkNode(xtarget);
|
447
|
+
rxml_node_modify_dom(self, obj, xmlAddChild);
|
466
448
|
}
|
467
449
|
else
|
468
450
|
{
|
@@ -472,18 +454,7 @@ static VALUE rxml_node_content_add(VALUE self, VALUE obj)
|
|
472
454
|
|
473
455
|
xmlNodeAddContent(xnode, (xmlChar*) StringValuePtr(str));
|
474
456
|
}
|
475
|
-
return
|
476
|
-
}
|
477
|
-
|
478
|
-
/*
|
479
|
-
* call-seq:
|
480
|
-
* node.child_add(node)
|
481
|
-
*
|
482
|
-
* Set a child node for this node.
|
483
|
-
*/
|
484
|
-
static VALUE rxml_node_child_add(VALUE self, VALUE rnode)
|
485
|
-
{
|
486
|
-
return rxml_node_child_set_aux(self, rnode);
|
457
|
+
return self;
|
487
458
|
}
|
488
459
|
|
489
460
|
/*
|
@@ -923,7 +894,7 @@ static VALUE rxml_node_name_set(VALUE self, VALUE name)
|
|
923
894
|
* call-seq:
|
924
895
|
* node.next -> XML::Node
|
925
896
|
*
|
926
|
-
*
|
897
|
+
* Returns the next sibling node if one exists.
|
927
898
|
*/
|
928
899
|
static VALUE rxml_node_next_get(VALUE self)
|
929
900
|
{
|
@@ -939,25 +910,17 @@ static VALUE rxml_node_next_get(VALUE self)
|
|
939
910
|
|
940
911
|
/*
|
941
912
|
* call-seq:
|
942
|
-
*
|
913
|
+
* curr_node.next = node
|
943
914
|
*
|
944
|
-
*
|
915
|
+
* Adds the specified node as the next sibling of the current node.
|
916
|
+
* If the node already exists in the document, it is first removed
|
917
|
+
* from its existing context. Any adjacent text nodes will be
|
918
|
+
* merged together, meaning the returned node may be different
|
919
|
+
* than the original node.
|
945
920
|
*/
|
946
921
|
static VALUE rxml_node_next_set(VALUE self, VALUE next)
|
947
922
|
{
|
948
|
-
|
949
|
-
|
950
|
-
if (rb_obj_is_kind_of(next, cXMLNode) == Qfalse)
|
951
|
-
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
952
|
-
|
953
|
-
Data_Get_Struct(self, xmlNode, xnode);
|
954
|
-
Data_Get_Struct(next, xmlNode, xnext);
|
955
|
-
|
956
|
-
xresult = xmlAddNextSibling(xnode, xnext);
|
957
|
-
if (xresult == NULL)
|
958
|
-
rxml_raise(&xmlLastError);
|
959
|
-
|
960
|
-
return rxml_node_wrap(xresult);
|
923
|
+
return rxml_node_modify_dom(self, next, xmlAddNextSibling);
|
961
924
|
}
|
962
925
|
|
963
926
|
/*
|
@@ -1050,25 +1013,17 @@ static VALUE rxml_node_prev_get(VALUE self)
|
|
1050
1013
|
|
1051
1014
|
/*
|
1052
1015
|
* call-seq:
|
1053
|
-
*
|
1016
|
+
* curr_node.prev = node
|
1054
1017
|
*
|
1055
|
-
*
|
1018
|
+
* Adds the specified node as the previous sibling of the current node.
|
1019
|
+
* If the node already exists in the document, it is first removed
|
1020
|
+
* from its existing context. Any adjacent text nodes will be
|
1021
|
+
* merged together, meaning the returned node may be different
|
1022
|
+
* than the original node.
|
1056
1023
|
*/
|
1057
1024
|
static VALUE rxml_node_prev_set(VALUE self, VALUE prev)
|
1058
1025
|
{
|
1059
|
-
|
1060
|
-
|
1061
|
-
if (rb_obj_is_kind_of(prev, cXMLNode) == Qfalse)
|
1062
|
-
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
1063
|
-
|
1064
|
-
Data_Get_Struct(self, xmlNode, xnode);
|
1065
|
-
Data_Get_Struct(prev, xmlNode, xprev);
|
1066
|
-
|
1067
|
-
xresult = xmlAddPrevSibling(xnode, xprev);
|
1068
|
-
if (xresult == NULL)
|
1069
|
-
rxml_raise(&xmlLastError);
|
1070
|
-
|
1071
|
-
return rxml_node_wrap(xresult);
|
1026
|
+
return rxml_node_modify_dom(self, prev, xmlAddPrevSibling);
|
1072
1027
|
}
|
1073
1028
|
|
1074
1029
|
/*
|
@@ -1114,51 +1069,52 @@ static VALUE rxml_node_property_set(VALUE self, VALUE name, VALUE value)
|
|
1114
1069
|
* call-seq:
|
1115
1070
|
* node.remove! -> node
|
1116
1071
|
*
|
1117
|
-
* Removes this node and its children from its
|
1118
|
-
*
|
1119
|
-
*
|
1120
|
-
|
1121
|
-
* Otherwise, the node will be freed once
|
1122
|
-
* any references to it go out of scope. */
|
1072
|
+
* Removes this node and its children from the document tree by setting its document,
|
1073
|
+
* parent and siblings to nil. You can add the returned node back into a document.
|
1074
|
+
* Otherwise, the node will be freed once any references to it go out of scope.
|
1075
|
+
*/
|
1123
1076
|
|
1124
1077
|
static VALUE rxml_node_remove_ex(VALUE self)
|
1125
1078
|
{
|
1126
|
-
xmlNodePtr xnode;
|
1079
|
+
xmlNodePtr xnode, xresult;
|
1127
1080
|
Data_Get_Struct(self, xmlNode, xnode);
|
1128
1081
|
|
1129
|
-
/*
|
1082
|
+
/* First unlink the node from its parent. */
|
1130
1083
|
xmlUnlinkNode(xnode);
|
1131
1084
|
|
1132
|
-
/* Now
|
1133
|
-
|
1134
|
-
|
1085
|
+
/* Now copy the node we want to remove and make the
|
1086
|
+
current Ruby object point to it. We do this because
|
1087
|
+
a node has a number of dependencies on its parent
|
1088
|
+
document - its name (if using a dictionary), entities,
|
1089
|
+
namespaces, etc. For a node to live on its own, it
|
1090
|
+
needs to get its own copies of this information.*/
|
1091
|
+
xresult = xmlDocCopyNode(xnode, NULL, 1);
|
1092
|
+
|
1093
|
+
/* Now free the original node. */
|
1094
|
+
xmlFreeNode(xnode);
|
1095
|
+
|
1096
|
+
/* Now wrap the new node */
|
1097
|
+
RDATA(self)->data = xresult;
|
1098
|
+
xresult->_private = (void*) self;
|
1135
1099
|
|
1136
1100
|
/* Now return the removed node so the user can
|
1137
|
-
|
1101
|
+
do something with it.*/
|
1138
1102
|
return self;
|
1139
1103
|
}
|
1140
1104
|
|
1141
1105
|
/*
|
1142
1106
|
* call-seq:
|
1143
|
-
*
|
1107
|
+
* curr_node.sibling = node
|
1144
1108
|
*
|
1145
|
-
*
|
1109
|
+
* Adds the specified node as the end of the current node's list
|
1110
|
+
* of siblings. If the node already exists in the document, it
|
1111
|
+
* is first removed from its existing context. Any adjacent text
|
1112
|
+
* nodes will be merged together, meaning the returned node may
|
1113
|
+
* be different than the original node.
|
1146
1114
|
*/
|
1147
1115
|
static VALUE rxml_node_sibling_set(VALUE self, VALUE sibling)
|
1148
1116
|
{
|
1149
|
-
|
1150
|
-
|
1151
|
-
if (rb_obj_is_kind_of(sibling, cXMLNode) == Qfalse)
|
1152
|
-
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
1153
|
-
|
1154
|
-
Data_Get_Struct(self, xmlNode, xnode);
|
1155
|
-
Data_Get_Struct(sibling, xmlNode, xsibling);
|
1156
|
-
|
1157
|
-
xresult = xmlAddSibling(xnode, xsibling);
|
1158
|
-
if (xresult == NULL)
|
1159
|
-
rxml_raise(&xmlLastError);
|
1160
|
-
|
1161
|
-
return rxml_node_wrap(xresult);
|
1117
|
+
return rxml_node_modify_dom(self, sibling, xmlAddSibling);
|
1162
1118
|
}
|
1163
1119
|
|
1164
1120
|
/*
|
@@ -1389,10 +1345,8 @@ void rxml_init_node(void)
|
|
1389
1345
|
rb_define_method(cXMLNode, "prev", rxml_node_prev_get, 0);
|
1390
1346
|
|
1391
1347
|
/* Modification */
|
1392
|
-
rb_define_method(cXMLNode, "<<", rxml_node_content_add, 1);
|
1393
1348
|
rb_define_method(cXMLNode, "[]=", rxml_node_property_set, 2);
|
1394
|
-
rb_define_method(cXMLNode, "
|
1395
|
-
rb_define_method(cXMLNode, "child=", rxml_node_child_set, 1);
|
1349
|
+
rb_define_method(cXMLNode, "<<", rxml_node_content_add, 1);
|
1396
1350
|
rb_define_method(cXMLNode, "sibling=", rxml_node_sibling_set, 1);
|
1397
1351
|
rb_define_method(cXMLNode, "next=", rxml_node_next_set, 1);
|
1398
1352
|
rb_define_method(cXMLNode, "prev=", rxml_node_prev_set, 1);
|