libxml-ruby 0.3.8 → 0.3.8.2
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/README +2 -2
- data/Rakefile +3 -2
- data/ext/xml/extconf.rb +7 -3
- data/ext/xml/libxml.c +2 -2
- data/ext/xml/libxml.h +2 -2
- data/ext/xml/libxml.rb +15 -15
- data/ext/xml/ruby_xml_attr.c +36 -20
- data/ext/xml/ruby_xml_attr.h +2 -2
- data/ext/xml/ruby_xml_attribute.c +5 -5
- data/ext/xml/ruby_xml_document.c +9 -11
- data/ext/xml/ruby_xml_node.c +305 -77
- data/ext/xml/ruby_xml_node.h +4 -3
- data/ext/xml/ruby_xml_node_set.c +4 -4
- data/ext/xml/ruby_xml_parser.c +10 -4
- data/ext/xml/ruby_xml_parser_context.c +2 -2
- data/ext/xml/ruby_xml_sax_parser.c +10 -2
- data/tests/copy_bug.rb +1 -1
- data/tests/copy_bug2.rb +32 -0
- data/tests/libxml_test.rb +1 -0
- data/tests/merge_bug.rb +56 -0
- data/tests/model/merge_bug_data.xml +58 -0
- data/tests/tc_xml_document_write3.rb +2 -2
- data/tests/tc_xml_node3.rb +2 -2
- data/tests/tc_xml_node4.rb +2 -2
- data/tests/tc_xml_node5.rb +53 -0
- data/tests/tc_xml_node6.rb +28 -0
- data/tests/tc_xml_node7.rb +28 -0
- data/tests/tc_xml_node8.rb +32 -0
- data/tests/tc_xml_node9.rb +32 -0
- data/tests/tc_xml_node_set2.rb +2 -2
- data/tests/tc_xml_node_xlink.rb +2 -2
- metadata +14 -6
data/ext/xml/ruby_xml_node.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: ruby_xml_node.c,v 1.
|
1
|
+
/* $Id: ruby_xml_node.c,v 1.9 2006/11/20 01:22:07 roscopeco Exp $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
@@ -10,6 +10,15 @@ VALUE eXMLNodeSetNamespace;
|
|
10
10
|
VALUE eXMLNodeFailedModify;
|
11
11
|
VALUE eXMLNodeUnknownType;
|
12
12
|
|
13
|
+
static VALUE
|
14
|
+
check_string_or_symbol( VALUE val ) {
|
15
|
+
if( TYPE(val) != T_STRING && TYPE(val) != T_SYMBOL ) {
|
16
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Symbol)",
|
17
|
+
rb_obj_classname(val) );
|
18
|
+
}
|
19
|
+
return rb_obj_as_string( val );
|
20
|
+
}
|
21
|
+
|
13
22
|
/*
|
14
23
|
* call-seq:
|
15
24
|
* node.attribute? => (true|false)
|
@@ -122,7 +131,7 @@ ruby_xml_node_comment_q(VALUE self) {
|
|
122
131
|
|
123
132
|
/*
|
124
133
|
* call-seq:
|
125
|
-
* node << ("string" | node)
|
134
|
+
* node << ("string" | node) => node
|
126
135
|
*
|
127
136
|
* Add the specified string or XML::Node to this node's
|
128
137
|
* content.
|
@@ -134,17 +143,18 @@ ruby_xml_node_content_add(VALUE self, VALUE obj) {
|
|
134
143
|
|
135
144
|
Data_Get_Struct(self, ruby_xml_node, node);
|
136
145
|
if (rb_obj_is_kind_of(obj, cXMLNode)) {
|
137
|
-
|
146
|
+
ruby_xml_node_child_set(self, obj);
|
147
|
+
return(self);
|
138
148
|
} else if (TYPE(obj) == T_STRING) {
|
139
149
|
xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(obj));
|
140
|
-
return(
|
150
|
+
return(self);
|
141
151
|
} else {
|
142
152
|
str = rb_obj_as_string(obj);
|
143
153
|
if (NIL_P(str) || TYPE(str) != T_STRING)
|
144
154
|
rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
|
145
155
|
|
146
156
|
xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(str));
|
147
|
-
return(
|
157
|
+
return(self);
|
148
158
|
}
|
149
159
|
}
|
150
160
|
|
@@ -206,11 +216,6 @@ ruby_xml_node_content_stripped_get(VALUE self) {
|
|
206
216
|
return(rb_str_new2((const char*)xmlNodeGetContent(rxn->node)));
|
207
217
|
}
|
208
218
|
|
209
|
-
////////////////////////////////////////////////////
|
210
|
-
// TODO This whole child thing seems to work in some odd ways.
|
211
|
-
// Try setting child= to a node with multiple children,
|
212
|
-
// then get it back through child= .
|
213
|
-
|
214
219
|
/*
|
215
220
|
* call-seq:
|
216
221
|
* node.child => node
|
@@ -252,7 +257,7 @@ ruby_xml_node_child_get(VALUE self) {
|
|
252
257
|
if (tmp == NULL)
|
253
258
|
return(Qnil);
|
254
259
|
else
|
255
|
-
return(
|
260
|
+
return(ruby_xml_node_new_ptr(cXMLNode, node->xd, tmp));
|
256
261
|
}
|
257
262
|
|
258
263
|
|
@@ -300,6 +305,7 @@ ruby_xml_node_child_q(VALUE self) {
|
|
300
305
|
}
|
301
306
|
|
302
307
|
|
308
|
+
// TODO Fixes below should be applied to sibling, prev, etc ?
|
303
309
|
/*
|
304
310
|
* call-seq:
|
305
311
|
* node.child = node
|
@@ -309,20 +315,45 @@ ruby_xml_node_child_q(VALUE self) {
|
|
309
315
|
VALUE
|
310
316
|
ruby_xml_node_child_set(VALUE self, VALUE rnode) {
|
311
317
|
ruby_xml_node *cnode, *pnode;
|
312
|
-
xmlNodePtr ret;
|
318
|
+
xmlNodePtr chld, ret;
|
319
|
+
ruby_xml_document *pdoc, *cdoc;
|
320
|
+
int ptr;
|
313
321
|
|
314
322
|
if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
|
315
323
|
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
316
324
|
|
317
325
|
Data_Get_Struct(self, ruby_xml_node, pnode);
|
318
326
|
Data_Get_Struct(rnode, ruby_xml_node, cnode);
|
319
|
-
|
320
|
-
|
327
|
+
|
328
|
+
chld = cnode->node;
|
329
|
+
|
330
|
+
// Only copy if both nodes are in documents, which are different.
|
331
|
+
if (pnode->xd && pnode->xd != Qnil) {
|
332
|
+
Data_Get_Struct(pnode->xd, ruby_xml_document, pdoc);
|
333
|
+
if (cnode->xd && cnode->xd != Qnil) {
|
334
|
+
Data_Get_Struct(cnode->xd, ruby_xml_document, cdoc);
|
335
|
+
if (cdoc->doc != pdoc->doc) {
|
336
|
+
chld = xmlDocCopyNode(chld, pdoc->doc, 1);
|
337
|
+
chld->_private = 0;
|
338
|
+
ptr = 1;
|
339
|
+
}
|
340
|
+
} else {
|
341
|
+
chld = xmlDocCopyNode(chld, pdoc->doc, 1);
|
342
|
+
chld->_private = 0;
|
343
|
+
ptr = 1;
|
344
|
+
}
|
345
|
+
} else {
|
346
|
+
chld->doc = NULL;
|
347
|
+
}
|
348
|
+
|
349
|
+
ret = xmlAddChild(pnode->node, chld);
|
321
350
|
if (ret == NULL)
|
322
351
|
rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
|
352
|
+
|
353
|
+
cnode->node = ret;
|
354
|
+
cnode->xd = pnode->xd;
|
323
355
|
|
324
|
-
|
325
|
-
return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
|
356
|
+
return(rnode);
|
326
357
|
}
|
327
358
|
|
328
359
|
////////////////////////////////////////////////
|
@@ -342,6 +373,9 @@ ruby_xml_node_doc(VALUE self) {
|
|
342
373
|
VALUE docobj;
|
343
374
|
|
344
375
|
Data_Get_Struct(self, ruby_xml_node, rxn);
|
376
|
+
|
377
|
+
if (rxn->xd)
|
378
|
+
return(rxn->xd);
|
345
379
|
|
346
380
|
switch (rxn->node->type) {
|
347
381
|
case XML_DOCUMENT_NODE:
|
@@ -634,18 +668,18 @@ VALUE
|
|
634
668
|
ruby_xml_node_find_first(int argc, VALUE *argv, VALUE self) {
|
635
669
|
VALUE ns = ruby_xml_node_find(argc, argv, self);
|
636
670
|
ruby_xml_node_set *rxnset;
|
671
|
+
VALUE nodeobj;
|
637
672
|
|
638
673
|
Data_Get_Struct(ns, ruby_xml_node_set, rxnset);
|
639
674
|
if (rxnset->node_set == NULL || rxnset->node_set->nodeNr < 1)
|
640
675
|
return(Qnil);
|
641
676
|
|
642
|
-
VALUE nodeobj;
|
643
677
|
switch(rxnset->node_set->nodeTab[0]->type) {
|
644
678
|
case XML_ATTRIBUTE_NODE:
|
645
679
|
nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[0]);
|
646
680
|
break;
|
647
681
|
default:
|
648
|
-
nodeobj =
|
682
|
+
nodeobj = ruby_xml_node_new_ptr(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]);
|
649
683
|
}
|
650
684
|
|
651
685
|
return(nodeobj);
|
@@ -670,12 +704,19 @@ ruby_xml_node_fragment_q(VALUE self) {
|
|
670
704
|
|
671
705
|
|
672
706
|
void ruby_xml_node_free(ruby_xml_node *rxn) {
|
673
|
-
if (rxn->node != NULL &&
|
674
|
-
|
675
|
-
|
676
|
-
rxn->node
|
707
|
+
if (rxn->node != NULL && // got a node?
|
708
|
+
rxn->node->parent == NULL && // unparented (otherwise, it gets freed with parent)
|
709
|
+
rxn->node->doc == NULL) { // No document? (otherwise, freed with doc)
|
710
|
+
if ((int)rxn->node->_private <= 1) {
|
711
|
+
// is null or last reference,
|
712
|
+
xmlFreeNode(rxn->node);
|
713
|
+
} else {
|
714
|
+
// other pointers remain
|
715
|
+
rxn->node->_private--;
|
716
|
+
}
|
677
717
|
}
|
678
718
|
|
719
|
+
rxn->node = NULL;
|
679
720
|
free(rxn);
|
680
721
|
}
|
681
722
|
|
@@ -718,14 +759,16 @@ ruby_xml_node_html_doc_q(VALUE self) {
|
|
718
759
|
/*
|
719
760
|
* call-seq:
|
720
761
|
* XML::Node.new(name, content = nil) => node
|
762
|
+
* XML::Node.new_element(name, content = nil) => node
|
721
763
|
*
|
722
|
-
* Create a new node with the specified name, optionally setting
|
764
|
+
* Create a new element node with the specified name, optionally setting
|
723
765
|
* the node's content.
|
724
766
|
*/
|
725
767
|
VALUE
|
726
768
|
ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
|
727
769
|
ruby_xml_node *rxn;
|
728
770
|
VALUE name, node, str;
|
771
|
+
xmlNodePtr newxn;
|
729
772
|
|
730
773
|
str = Qnil;
|
731
774
|
|
@@ -746,11 +789,13 @@ ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
|
|
746
789
|
* the object. Sneaky, but effective. Probably should use a goto
|
747
790
|
* instead. */
|
748
791
|
case 1:
|
749
|
-
name = argv[0];
|
750
|
-
|
751
|
-
node = ruby_xml_node_new(class,
|
792
|
+
name = check_string_or_symbol( argv[0] );
|
793
|
+
newxn = xmlNewNode(NULL, (xmlChar*)StringValuePtr(name));
|
794
|
+
node = ruby_xml_node_new(class, newxn);
|
795
|
+
|
752
796
|
Data_Get_Struct(node, ruby_xml_node, rxn);
|
753
|
-
|
797
|
+
|
798
|
+
/* TODO How would this happen? Shouldn't we raise on it anyway? */
|
754
799
|
if (rxn->node == NULL)
|
755
800
|
return(Qnil);
|
756
801
|
|
@@ -766,7 +811,86 @@ ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
|
|
766
811
|
return(node);
|
767
812
|
}
|
768
813
|
|
814
|
+
/*
|
815
|
+
* call-seq:
|
816
|
+
* XML::Node.new_cdata(content = nil) => node
|
817
|
+
*
|
818
|
+
* Create a new #CDATA node, optionally setting
|
819
|
+
* the node's content.
|
820
|
+
*/
|
821
|
+
VALUE
|
822
|
+
ruby_xml_node_cdata_initialize(int argc, VALUE *argv, VALUE class) {
|
823
|
+
xmlNode *xnode;
|
824
|
+
VALUE node, str;
|
825
|
+
|
826
|
+
str = Qnil;
|
827
|
+
|
828
|
+
switch(argc) {
|
829
|
+
case 1:
|
830
|
+
str = argv[0];
|
831
|
+
Check_Type(str, T_STRING);
|
832
|
+
if (!NIL_P(str)) {
|
833
|
+
xnode = xmlNewCDataBlock(NULL, (xmlChar*)StringValuePtr(str), xmlStrlen((xmlChar*)StringValuePtr(str)));
|
834
|
+
} else {
|
835
|
+
xnode = xmlNewCDataBlock(NULL, NULL , 0);
|
836
|
+
}
|
769
837
|
|
838
|
+
if (xnode == NULL)
|
839
|
+
return(Qnil);
|
840
|
+
|
841
|
+
node = ruby_xml_node_new(class, xnode);
|
842
|
+
|
843
|
+
break;
|
844
|
+
|
845
|
+
default:
|
846
|
+
rb_raise(rb_eArgError, "wrong number of arguments (1)");
|
847
|
+
}
|
848
|
+
|
849
|
+
return(node);
|
850
|
+
}
|
851
|
+
|
852
|
+
|
853
|
+
/*
|
854
|
+
* call-seq:
|
855
|
+
* XML::Node.new_comment(content = nil) => node
|
856
|
+
*
|
857
|
+
* Create a new comment node, optionally setting
|
858
|
+
* the node's content.
|
859
|
+
*
|
860
|
+
*/
|
861
|
+
VALUE
|
862
|
+
ruby_xml_node_comment_initialize(int argc, VALUE *argv, VALUE class) {
|
863
|
+
xmlNode *xnode;
|
864
|
+
VALUE node, str;
|
865
|
+
|
866
|
+
str = Qnil;
|
867
|
+
|
868
|
+
switch(argc) {
|
869
|
+
case 1:
|
870
|
+
str = argv[0];
|
871
|
+
Check_Type(str, T_STRING);
|
872
|
+
// TODO xmlNewComment wrongly? adds \n before and after the comment
|
873
|
+
if (!NIL_P(str)) {
|
874
|
+
xnode = xmlNewComment((xmlChar*)StringValuePtr(str));
|
875
|
+
} else {
|
876
|
+
xnode = xmlNewComment(NULL);
|
877
|
+
}
|
878
|
+
|
879
|
+
if (xnode == NULL)
|
880
|
+
return(Qnil);
|
881
|
+
|
882
|
+
node = ruby_xml_node_new(class, xnode);
|
883
|
+
|
884
|
+
break;
|
885
|
+
|
886
|
+
default:
|
887
|
+
rb_raise(rb_eArgError, "wrong number of arguments (1)");
|
888
|
+
}
|
889
|
+
|
890
|
+
return(node);
|
891
|
+
}
|
892
|
+
|
893
|
+
|
770
894
|
/*
|
771
895
|
* call-seq:
|
772
896
|
* node.lang => "string"
|
@@ -850,7 +974,7 @@ ruby_xml_node_last_get(VALUE self) {
|
|
850
974
|
if (node == NULL)
|
851
975
|
return(Qnil);
|
852
976
|
else
|
853
|
-
return(
|
977
|
+
return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
|
854
978
|
}
|
855
979
|
|
856
980
|
|
@@ -1213,33 +1337,85 @@ ruby_xml_node_namespace_q(VALUE self) {
|
|
1213
1337
|
return(Qfalse);
|
1214
1338
|
}
|
1215
1339
|
|
1216
|
-
|
1340
|
+
/* TODO new_ptr and new3 are obsolete, should be consolidated */
|
1217
1341
|
VALUE
|
1218
1342
|
ruby_xml_node_new(VALUE class, xmlNodePtr node) {
|
1219
|
-
|
1343
|
+
return ruby_xml_node_new_ptr(class, Qnil, node);
|
1344
|
+
}
|
1220
1345
|
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
return(Data_Wrap_Struct(class, ruby_xml_node_mark,
|
1226
|
-
ruby_xml_node_free, rxn));
|
1346
|
+
|
1347
|
+
VALUE
|
1348
|
+
ruby_xml_node_new_ptr(VALUE class, VALUE xd, xmlNodePtr node) {
|
1349
|
+
return ruby_xml_node_new3(class, xd, node, 1);
|
1227
1350
|
}
|
1228
1351
|
|
1229
1352
|
|
1353
|
+
/* TODO ptr arg is obsolete, should be removed */
|
1354
|
+
|
1355
|
+
/* Here's how this works:
|
1356
|
+
*
|
1357
|
+
* All nodes are 'pointer' nodes, but no node owns the xmlNode
|
1358
|
+
* structure they're associated with. Instead, we maintain a
|
1359
|
+
* count of the number of VALUEs out there wrapping a given
|
1360
|
+
* node, in the nodes _private member. When we wrap a node,
|
1361
|
+
* this is incremented.
|
1362
|
+
*
|
1363
|
+
* In ruby_xml_node_free , the count is checked and if it's
|
1364
|
+
* either NULL or 1 (indicating non-wrapped, or that this is
|
1365
|
+
* the last reference) then the node is freed along with the
|
1366
|
+
* ruby_xml_node that points to it. Otherwise, just the
|
1367
|
+
* ruby struct is freed and the node is retained.
|
1368
|
+
*
|
1369
|
+
* This fixes a problem with the old setup whereby ruby_xml_nodes
|
1370
|
+
* with is_ptr = 1 could remain after the node they were pointing
|
1371
|
+
* to had been collected. It also helps to ensure we're
|
1372
|
+
* threadsafe (according to the libxml2 threadsafety rules).
|
1373
|
+
*
|
1374
|
+
* N.B. The XD document pointer is very important - when time
|
1375
|
+
* comes to free a node, we *must* not free nodes that belong
|
1376
|
+
* to a document, or have a parent - they will be freed either
|
1377
|
+
* with the document or with the parent (xmlFreeNode calls
|
1378
|
+
* xmlFreeNodeList on the kids). You need to make sure that
|
1379
|
+
* you keep the XD up to date with the node->doc.
|
1380
|
+
*
|
1381
|
+
* TODO there should be a func that does that.
|
1382
|
+
*
|
1383
|
+
* N.B. You can't do this any more:
|
1384
|
+
*
|
1385
|
+
* node = ruby_xml_node_new3(class, NULL);
|
1386
|
+
* Data_Get_Struct(node, ruby_xml_node, rxn);
|
1387
|
+
* rxn->node = someXmlNode;
|
1388
|
+
*
|
1389
|
+
* You *must* pass in the node when your making the new rxn.
|
1390
|
+
* This saves confusion about who owns what node, and lets the
|
1391
|
+
* refcounts stay consistent.
|
1392
|
+
*/
|
1230
1393
|
VALUE
|
1231
|
-
|
1394
|
+
ruby_xml_node_new3(VALUE class, VALUE xd, xmlNodePtr node, int ptr) {
|
1232
1395
|
ruby_xml_node *rxn;
|
1233
|
-
|
1234
1396
|
rxn = ALLOC(ruby_xml_node);
|
1235
|
-
|
1397
|
+
|
1236
1398
|
rxn->node = node;
|
1237
|
-
if (
|
1399
|
+
if (node->_private) {
|
1400
|
+
node->_private++;
|
1401
|
+
} else {
|
1402
|
+
node->_private = (void*)1;
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
if (NIL_P(xd)) {
|
1238
1406
|
rxn->xd = Qnil;
|
1239
|
-
|
1407
|
+
rxn->node->doc = NULL;
|
1408
|
+
} else {
|
1409
|
+
/* Have to set node->doc too so we don't doublefree this node */
|
1410
|
+
ruby_xml_document *xdoc;
|
1411
|
+
Data_Get_Struct(xd, ruby_xml_document, xdoc);
|
1412
|
+
|
1240
1413
|
rxn->xd = xd;
|
1414
|
+
rxn->node->doc = xdoc->doc;
|
1415
|
+
}
|
1416
|
+
|
1241
1417
|
return(Data_Wrap_Struct(class, ruby_xml_node_mark,
|
1242
|
-
|
1418
|
+
ruby_xml_node_free, rxn));
|
1243
1419
|
}
|
1244
1420
|
|
1245
1421
|
|
@@ -1280,10 +1456,11 @@ ruby_xml_node_next_get(VALUE self) {
|
|
1280
1456
|
break;
|
1281
1457
|
}
|
1282
1458
|
|
1283
|
-
if (node == NULL)
|
1459
|
+
if (node == NULL) {
|
1284
1460
|
return(Qnil);
|
1285
|
-
else
|
1286
|
-
return(
|
1461
|
+
} else {
|
1462
|
+
return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
|
1463
|
+
}
|
1287
1464
|
}
|
1288
1465
|
|
1289
1466
|
|
@@ -1331,6 +1508,31 @@ ruby_xml_node_next_q(VALUE self) {
|
|
1331
1508
|
}
|
1332
1509
|
|
1333
1510
|
|
1511
|
+
/*
|
1512
|
+
* call-seq:
|
1513
|
+
* node.next = node
|
1514
|
+
*
|
1515
|
+
* Insert the specified node as this node's next sibling.
|
1516
|
+
*/
|
1517
|
+
VALUE
|
1518
|
+
ruby_xml_node_next_set(VALUE self, VALUE rnode) {
|
1519
|
+
ruby_xml_node *cnode, *pnode;
|
1520
|
+
xmlNodePtr ret;
|
1521
|
+
|
1522
|
+
if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
|
1523
|
+
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
1524
|
+
|
1525
|
+
Data_Get_Struct(self, ruby_xml_node, pnode);
|
1526
|
+
Data_Get_Struct(rnode, ruby_xml_node, cnode);
|
1527
|
+
|
1528
|
+
ret = xmlAddNextSibling(pnode->node, cnode->node);
|
1529
|
+
if (ret == NULL)
|
1530
|
+
rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
|
1531
|
+
|
1532
|
+
return(ruby_xml_node_new_ptr(cXMLNode, pnode->xd, ret));
|
1533
|
+
}
|
1534
|
+
|
1535
|
+
|
1334
1536
|
/*
|
1335
1537
|
* call-seq:
|
1336
1538
|
* node.notation? => (true|false)
|
@@ -1440,7 +1642,7 @@ ruby_xml_node_parent_get(VALUE self) {
|
|
1440
1642
|
if (node == NULL)
|
1441
1643
|
return(Qnil);
|
1442
1644
|
else
|
1443
|
-
return(
|
1645
|
+
return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
|
1444
1646
|
}
|
1445
1647
|
|
1446
1648
|
|
@@ -1562,18 +1764,18 @@ ruby_xml_node_prev_get(VALUE self) {
|
|
1562
1764
|
case XML_ATTRIBUTE_NODE:
|
1563
1765
|
{
|
1564
1766
|
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
|
1565
|
-
node = (xmlNodePtr) attr->
|
1767
|
+
node = (xmlNodePtr) attr->prev;
|
1566
1768
|
}
|
1567
1769
|
break;
|
1568
1770
|
default:
|
1569
|
-
node = rxn->node->
|
1771
|
+
node = rxn->node->prev;
|
1570
1772
|
break;
|
1571
1773
|
}
|
1572
1774
|
|
1573
1775
|
if (node == NULL)
|
1574
1776
|
return(Qnil);
|
1575
1777
|
else
|
1576
|
-
return(
|
1778
|
+
return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
|
1577
1779
|
}
|
1578
1780
|
|
1579
1781
|
|
@@ -1602,11 +1804,11 @@ ruby_xml_node_prev_q(VALUE self) {
|
|
1602
1804
|
case XML_ATTRIBUTE_NODE:
|
1603
1805
|
{
|
1604
1806
|
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
|
1605
|
-
node = (xmlNodePtr) attr->
|
1807
|
+
node = (xmlNodePtr) attr->prev;
|
1606
1808
|
}
|
1607
1809
|
break;
|
1608
1810
|
default:
|
1609
|
-
node = rxn->node->
|
1811
|
+
node = rxn->node->prev;
|
1610
1812
|
break;
|
1611
1813
|
}
|
1612
1814
|
|
@@ -1617,6 +1819,31 @@ ruby_xml_node_prev_q(VALUE self) {
|
|
1617
1819
|
}
|
1618
1820
|
|
1619
1821
|
|
1822
|
+
/*
|
1823
|
+
* call-seq:
|
1824
|
+
* node.prev = node
|
1825
|
+
*
|
1826
|
+
* Insert the specified node as this node's previous sibling.
|
1827
|
+
*/
|
1828
|
+
VALUE
|
1829
|
+
ruby_xml_node_prev_set(VALUE self, VALUE rnode) {
|
1830
|
+
ruby_xml_node *cnode, *pnode;
|
1831
|
+
xmlNodePtr ret;
|
1832
|
+
|
1833
|
+
if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
|
1834
|
+
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
|
1835
|
+
|
1836
|
+
Data_Get_Struct(self, ruby_xml_node, pnode);
|
1837
|
+
Data_Get_Struct(rnode, ruby_xml_node, cnode);
|
1838
|
+
|
1839
|
+
ret = xmlAddPrevSibling(pnode->node, cnode->node);
|
1840
|
+
if (ret == NULL)
|
1841
|
+
rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
|
1842
|
+
|
1843
|
+
return(ruby_xml_node_new_ptr(cXMLNode, pnode->xd, ret));
|
1844
|
+
}
|
1845
|
+
|
1846
|
+
|
1620
1847
|
/*
|
1621
1848
|
* call-seq:
|
1622
1849
|
* node.property("name") => "string"
|
@@ -1630,8 +1857,8 @@ ruby_xml_node_property_get(VALUE self, VALUE prop) {
|
|
1630
1857
|
xmlChar *p;
|
1631
1858
|
VALUE r;
|
1632
1859
|
|
1633
|
-
|
1634
|
-
|
1860
|
+
prop = check_string_or_symbol( prop );
|
1861
|
+
|
1635
1862
|
Data_Get_Struct(self, ruby_xml_node, rxn);
|
1636
1863
|
p = xmlGetProp(rxn->node, (xmlChar*)StringValuePtr(prop));
|
1637
1864
|
|
@@ -1655,12 +1882,10 @@ ruby_xml_node_property_get(VALUE self, VALUE prop) {
|
|
1655
1882
|
VALUE
|
1656
1883
|
ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) {
|
1657
1884
|
ruby_xml_node *node;
|
1658
|
-
ruby_xml_attr *rxa;
|
1659
1885
|
xmlAttrPtr attr;
|
1660
|
-
VALUE rattr;
|
1661
1886
|
|
1662
|
-
|
1663
|
-
|
1887
|
+
key = check_string_or_symbol( key );
|
1888
|
+
Data_Get_Struct(self, ruby_xml_node, node);
|
1664
1889
|
|
1665
1890
|
if( val == Qnil ) {
|
1666
1891
|
attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), NULL);
|
@@ -1676,10 +1901,7 @@ ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) {
|
|
1676
1901
|
if (attr == NULL)
|
1677
1902
|
return(Qnil);
|
1678
1903
|
}
|
1679
|
-
|
1680
|
-
Data_Get_Struct(rattr, ruby_xml_attr, rxa);
|
1681
|
-
rxa->is_ptr = 1;
|
1682
|
-
return(rattr);
|
1904
|
+
return(ruby_xml_attr_new(cXMLAttr, node->xd, attr));
|
1683
1905
|
}
|
1684
1906
|
|
1685
1907
|
|
@@ -1778,11 +2000,14 @@ ruby_xml_node_search_ns(VALUE self, VALUE ns) {
|
|
1778
2000
|
}
|
1779
2001
|
|
1780
2002
|
|
2003
|
+
/* TODO Obsolete, remove */
|
1781
2004
|
VALUE
|
1782
2005
|
ruby_xml_node_set_ptr(VALUE node, int is_ptr) {
|
2006
|
+
/*
|
1783
2007
|
ruby_xml_node *rxn;
|
1784
2008
|
Data_Get_Struct(node, ruby_xml_node, rxn);
|
1785
2009
|
rxn->is_ptr = is_ptr;
|
2010
|
+
*/
|
1786
2011
|
return(Qtrue);
|
1787
2012
|
}
|
1788
2013
|
|
@@ -1808,8 +2033,7 @@ ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
|
|
1808
2033
|
if (ret == NULL)
|
1809
2034
|
rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
|
1810
2035
|
|
1811
|
-
|
1812
|
-
return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
|
2036
|
+
return(ruby_xml_node_new_ptr(cXMLNode, pnode->xd, ret));
|
1813
2037
|
}
|
1814
2038
|
|
1815
2039
|
|
@@ -1999,8 +2223,6 @@ ruby_xml_node_xinclude_start_q(VALUE self) {
|
|
1999
2223
|
}
|
2000
2224
|
|
2001
2225
|
|
2002
|
-
// TODO my gut tells me this is where our sigseg etc. problems start...
|
2003
|
-
|
2004
2226
|
/*
|
2005
2227
|
* call-seq:
|
2006
2228
|
* node.copy => node
|
@@ -2009,19 +2231,18 @@ ruby_xml_node_xinclude_start_q(VALUE self) {
|
|
2009
2231
|
*/
|
2010
2232
|
VALUE
|
2011
2233
|
ruby_xml_node_copy(VALUE self, VALUE deep) { /* MUFF */
|
2012
|
-
ruby_xml_node *rxn
|
2013
|
-
|
2234
|
+
ruby_xml_node *rxn;
|
2235
|
+
xmlNode *copy;
|
2014
2236
|
|
2015
2237
|
Data_Get_Struct(self, ruby_xml_node, rxn);
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
return(
|
2023
|
-
|
2024
|
-
return n_node;
|
2238
|
+
copy = xmlCopyNode( rxn->node, ((deep==Qnil)||(deep==Qfalse))?0:1 );
|
2239
|
+
copy->_private = (void*)0;
|
2240
|
+
|
2241
|
+
if (copy == NULL) {
|
2242
|
+
return Qnil;
|
2243
|
+
} else {
|
2244
|
+
return(ruby_xml_node_new(cXMLNode, copy));
|
2245
|
+
}
|
2025
2246
|
}
|
2026
2247
|
|
2027
2248
|
|
@@ -2053,7 +2274,12 @@ ruby_init_xml_node(void) {
|
|
2053
2274
|
rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
|
2054
2275
|
|
2055
2276
|
rb_define_singleton_method(cXMLNode, "new", ruby_xml_node_initialize, -1);
|
2056
|
-
|
2277
|
+
rb_define_singleton_method(cXMLNode, "new_cdata", ruby_xml_node_cdata_initialize, -1);
|
2278
|
+
rb_define_singleton_method(cXMLNode, "new_comment", ruby_xml_node_comment_initialize, -1);
|
2279
|
+
|
2280
|
+
VALUE singleton = rb_singleton_class(cXMLNode);
|
2281
|
+
rb_define_alias(singleton, "new_element", "new");
|
2282
|
+
|
2057
2283
|
rb_define_method(cXMLNode, "<<", ruby_xml_node_content_add, 1);
|
2058
2284
|
rb_define_method(cXMLNode, "[]", ruby_xml_node_property_get, 1);
|
2059
2285
|
rb_define_method(cXMLNode, "[]=", ruby_xml_node_property_set, 2);
|
@@ -2104,6 +2330,7 @@ ruby_init_xml_node(void) {
|
|
2104
2330
|
rb_define_method(cXMLNode, "namespace=", ruby_xml_node_namespace_set, -1);
|
2105
2331
|
rb_define_method(cXMLNode, "next", ruby_xml_node_next_get, 0);
|
2106
2332
|
rb_define_method(cXMLNode, "next?", ruby_xml_node_next_q, 0);
|
2333
|
+
rb_define_method(cXMLNode, "next=", ruby_xml_node_next_set, 1);
|
2107
2334
|
rb_define_method(cXMLNode, "node_type", ruby_xml_node_type, 0);
|
2108
2335
|
rb_define_method(cXMLNode, "node_type_name", ruby_xml_node_type_name, 0);
|
2109
2336
|
rb_define_method(cXMLNode, "notation?", ruby_xml_node_notation_q, 0);
|
@@ -2118,6 +2345,7 @@ ruby_init_xml_node(void) {
|
|
2118
2345
|
rb_define_method(cXMLNode, "pointer", ruby_xml_node_pointer, 1);
|
2119
2346
|
rb_define_method(cXMLNode, "prev", ruby_xml_node_prev_get, 0);
|
2120
2347
|
rb_define_method(cXMLNode, "prev?", ruby_xml_node_prev_q, 0);
|
2348
|
+
rb_define_method(cXMLNode, "prev=", ruby_xml_node_prev_set, 1);
|
2121
2349
|
rb_define_method(cXMLNode, "property", ruby_xml_node_property_get, 1);
|
2122
2350
|
rb_define_method(cXMLNode, "properties", ruby_xml_node_properties_get, 0);
|
2123
2351
|
rb_define_method(cXMLNode, "properties?", ruby_xml_node_properties_q, 0);
|