libxml-ruby 0.3.8 → 0.3.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_node.c,v 1.3 2006/04/12 12:08:39 roscopeco Exp $ */
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
- return(ruby_xml_node_child_set(self, obj));
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(obj);
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(obj);
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(ruby_xml_node_new2(cXMLNode, node->xd, tmp));
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
- ret = xmlAddChild(pnode->node, cnode->node);
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
- ruby_xml_node_set_ptr(rnode, 1);
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 = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]);
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 && !rxn->is_ptr) {
674
- xmlUnlinkNode(rxn->node);
675
- xmlFreeNode(rxn->node);
676
- rxn->node = NULL;
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
- Check_Type(name, T_STRING);
751
- node = ruby_xml_node_new(class, NULL);
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
- rxn->node = xmlNewNode(NULL, (xmlChar*)StringValuePtr(name));
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(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
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
- ruby_xml_node *rxn;
1343
+ return ruby_xml_node_new_ptr(class, Qnil, node);
1344
+ }
1220
1345
 
1221
- rxn = ALLOC(ruby_xml_node);
1222
- rxn->is_ptr = 0;
1223
- rxn->node = node;
1224
- rxn->xd = Qnil;
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
- ruby_xml_node_new2(VALUE class, VALUE xd, xmlNodePtr node) {
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
- rxn->is_ptr = 1;
1397
+
1236
1398
  rxn->node = node;
1237
- if (NIL_P(xd))
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
- else
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
- ruby_xml_node_free, rxn));
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(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
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(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
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->next;
1767
+ node = (xmlNodePtr) attr->prev;
1566
1768
  }
1567
1769
  break;
1568
1770
  default:
1569
- node = rxn->node->next;
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(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
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->next;
1807
+ node = (xmlNodePtr) attr->prev;
1606
1808
  }
1607
1809
  break;
1608
1810
  default:
1609
- node = rxn->node->next;
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
- Check_Type(prop, T_STRING);
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
- Data_Get_Struct(self, ruby_xml_node, node);
1663
- Check_Type(key, T_STRING);
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
- rattr = ruby_xml_attr_new(cXMLAttr, node->xd, attr);
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
- cnode->is_ptr = 1;
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, *n_rxn;
2013
- VALUE n_node;
2234
+ ruby_xml_node *rxn;
2235
+ xmlNode *copy;
2014
2236
 
2015
2237
  Data_Get_Struct(self, ruby_xml_node, rxn);
2016
-
2017
- n_node = ruby_xml_node_new(cXMLNode, NULL); // class??
2018
- Data_Get_Struct(n_node, ruby_xml_node, n_rxn);
2019
-
2020
- n_rxn->node = xmlCopyNode( rxn->node, ((deep==Qnil)||(deep==Qfalse))?0:1 );
2021
- if (rxn->node == NULL)
2022
- return(Qnil);
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);