libxml-ruby 0.3.8.4 → 0.5.0

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.
Files changed (77) hide show
  1. data/CHANGELOG +6 -0
  2. data/LICENSE +1 -1
  3. data/README +1 -1
  4. data/Rakefile +8 -5
  5. data/TODO +1 -1
  6. data/ext/xml/extconf.rb +4 -5
  7. data/ext/xml/libxml.c +5 -2
  8. data/ext/xml/libxml.h +16 -7
  9. data/ext/xml/libxml.rb +3 -3
  10. data/ext/xml/ruby_xml_attr.c +118 -99
  11. data/ext/xml/ruby_xml_attr.h +4 -7
  12. data/ext/xml/ruby_xml_document.c +131 -170
  13. data/ext/xml/ruby_xml_document.h +5 -9
  14. data/ext/xml/ruby_xml_html_parser.c +453 -0
  15. data/ext/xml/ruby_xml_html_parser.h +29 -0
  16. data/ext/xml/ruby_xml_node.c +219 -253
  17. data/ext/xml/ruby_xml_node.h +4 -7
  18. data/ext/xml/ruby_xml_node_set.c +6 -6
  19. data/ext/xml/ruby_xml_node_set.h +1 -1
  20. data/ext/xml/ruby_xml_ns.c +1 -1
  21. data/ext/xml/ruby_xml_ns.h +1 -1
  22. data/ext/xml/ruby_xml_parser.c +5 -8
  23. data/ext/xml/ruby_xml_parser.h +1 -1
  24. data/ext/xml/ruby_xml_parser_context.c +3 -4
  25. data/ext/xml/ruby_xml_parser_context.h +1 -1
  26. data/ext/xml/ruby_xml_reader.c +893 -0
  27. data/ext/xml/ruby_xml_reader.h +14 -0
  28. data/ext/xml/ruby_xml_sax_parser.c +255 -204
  29. data/ext/xml/ruby_xml_sax_parser.h +6 -2
  30. data/ext/xml/ruby_xml_tree.c +1 -1
  31. data/ext/xml/ruby_xml_tree.h +1 -1
  32. data/ext/xml/ruby_xml_xinclude.c +1 -1
  33. data/ext/xml/ruby_xml_xinclude.h +1 -1
  34. data/ext/xml/ruby_xml_xpath.c +3 -2
  35. data/ext/xml/ruby_xml_xpath.h +1 -1
  36. data/ext/xml/ruby_xml_xpath_context.c +4 -4
  37. data/ext/xml/ruby_xml_xpath_context.h +1 -1
  38. data/ext/xml/ruby_xml_xpointer.c +10 -4
  39. data/ext/xml/ruby_xml_xpointer.h +1 -1
  40. data/ext/xml/ruby_xml_xpointer_context.c +1 -1
  41. data/ext/xml/ruby_xml_xpointer_context.h +1 -1
  42. data/ext/xml/sax_parser_callbacks.inc +55 -54
  43. data/tests/model/rubynet_project +1 -1
  44. data/tests/model/simple.xml +7 -0
  45. data/tests/tc_xml_document.rb +1 -1
  46. data/tests/tc_xml_document_write.rb +1 -1
  47. data/tests/tc_xml_document_write2.rb +1 -1
  48. data/tests/tc_xml_document_write3.rb +1 -1
  49. data/tests/tc_xml_html_parser.rb +60 -0
  50. data/tests/tc_xml_node.rb +1 -1
  51. data/tests/tc_xml_node2.rb +1 -1
  52. data/tests/tc_xml_node3.rb +1 -1
  53. data/tests/tc_xml_node4.rb +8 -5
  54. data/tests/tc_xml_node5.rb +1 -1
  55. data/tests/tc_xml_node6.rb +1 -1
  56. data/tests/tc_xml_node7.rb +1 -1
  57. data/tests/tc_xml_node_set.rb +1 -1
  58. data/tests/tc_xml_node_set2.rb +1 -1
  59. data/tests/tc_xml_node_xlink.rb +1 -1
  60. data/tests/tc_xml_parser.rb +5 -1
  61. data/tests/tc_xml_parser2.rb +1 -1
  62. data/tests/tc_xml_parser3.rb +1 -1
  63. data/tests/tc_xml_parser4.rb +1 -1
  64. data/tests/tc_xml_parser5.rb +1 -1
  65. data/tests/tc_xml_parser6.rb +1 -1
  66. data/tests/tc_xml_parser7.rb +1 -1
  67. data/tests/tc_xml_parser8.rb +1 -1
  68. data/tests/tc_xml_parser_context.rb +1 -1
  69. data/tests/tc_xml_reader.rb +101 -0
  70. data/tests/tc_xml_sax_parser.rb +95 -0
  71. data/tests/tc_xml_xinclude.rb +1 -1
  72. data/tests/tc_xml_xpath.rb +1 -1
  73. data/tests/tc_xml_xpointer.rb +1 -1
  74. metadata +79 -73
  75. data/ext/xml/ruby_xml_attribute.c +0 -224
  76. data/ext/xml/ruby_xml_attribute.h +0 -21
  77. data/tests/test_xml_sax_parser.rb +0 -64
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_node.c,v 1.9.2.3 2006/11/27 10:32:01 roscopeco Exp $ */
1
+ /* $Id: ruby_xml_node.c 138 2007-08-29 18:00:35Z danj $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -142,6 +142,10 @@ ruby_xml_node_content_add(VALUE self, VALUE obj) {
142
142
  VALUE str;
143
143
 
144
144
  Data_Get_Struct(self, ruby_xml_node, node);
145
+ /* XXX This should only be legal for a CDATA type node, I think,
146
+ * resulting in a merge of content, as if a string were passed
147
+ * danj 070827
148
+ */
145
149
  if (rb_obj_is_kind_of(obj, cXMLNode)) {
146
150
  ruby_xml_node_child_set(self, obj);
147
151
  return(self);
@@ -191,6 +195,7 @@ ruby_xml_node_content_set(VALUE self, VALUE content) {
191
195
 
192
196
  Check_Type(content, T_STRING);
193
197
  Data_Get_Struct(self, ruby_xml_node, node);
198
+ // XXX docs indicate need for escaping entites, need to be done? danj
194
199
  xmlNodeSetContent(node->node, (xmlChar*)StringValuePtr(content));
195
200
  return(Qtrue);
196
201
  }
@@ -257,7 +262,7 @@ ruby_xml_node_child_get(VALUE self) {
257
262
  if (tmp == NULL)
258
263
  return(Qnil);
259
264
  else
260
- return(ruby_xml_node_new_ptr(cXMLNode, node->xd, tmp));
265
+ return(ruby_xml_node2_wrap(cXMLNode, tmp));
261
266
  }
262
267
 
263
268
 
@@ -316,7 +321,7 @@ VALUE
316
321
  ruby_xml_node_child_set(VALUE self, VALUE rnode) {
317
322
  ruby_xml_node *cnode, *pnode;
318
323
  xmlNodePtr chld, ret;
319
- ruby_xml_document *pdoc, *cdoc;
324
+ ruby_xml_document_t *pdoc, *cdoc;
320
325
  int ptr;
321
326
 
322
327
  if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
@@ -326,12 +331,13 @@ ruby_xml_node_child_set(VALUE self, VALUE rnode) {
326
331
  Data_Get_Struct(rnode, ruby_xml_node, cnode);
327
332
 
328
333
  chld = cnode->node;
329
-
334
+
335
+ #ifdef IGNORE
330
336
  // Only copy if both nodes are in documents, which are different.
331
337
  if (pnode->xd && pnode->xd != Qnil) {
332
- Data_Get_Struct(pnode->xd, ruby_xml_document, pdoc);
338
+ Data_Get_Struct(pnode->xd, ruby_xml_document_t, pdoc);
333
339
  if (cnode->xd && cnode->xd != Qnil) {
334
- Data_Get_Struct(cnode->xd, ruby_xml_document, cdoc);
340
+ Data_Get_Struct(cnode->xd, ruby_xml_document_t, cdoc);
335
341
  if (cdoc->doc != pdoc->doc) {
336
342
  chld = xmlDocCopyNode(chld, pdoc->doc, 1);
337
343
  chld->_private = 0;
@@ -345,20 +351,15 @@ ruby_xml_node_child_set(VALUE self, VALUE rnode) {
345
351
  } else {
346
352
  chld->doc = NULL;
347
353
  }
354
+ #endif
348
355
 
349
356
  ret = xmlAddChild(pnode->node, chld);
350
357
  if (ret == NULL)
351
358
  rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
352
359
 
353
- cnode->node = ret;
354
- cnode->xd = pnode->xd;
355
-
356
- return(rnode);
360
+ return ruby_xml_node2_wrap(cXMLNode,ret);
357
361
  }
358
362
 
359
- ////////////////////////////////////////////////
360
- // TODO new Documents seem to be created quite readily...
361
-
362
363
  /*
363
364
  * call-seq:
364
365
  * node.doc => document
@@ -367,16 +368,13 @@ ruby_xml_node_child_set(VALUE self, VALUE rnode) {
367
368
  */
368
369
  VALUE
369
370
  ruby_xml_node_doc(VALUE self) {
370
- ruby_xml_document *rxd;
371
+ ruby_xml_document_t *rxd;
371
372
  ruby_xml_node *rxn;
372
- xmlDocPtr doc;
373
+ xmlDocPtr doc=NULL;
373
374
  VALUE docobj;
374
375
 
375
376
  Data_Get_Struct(self, ruby_xml_node, rxn);
376
377
 
377
- if (rxn->xd)
378
- return(rxn->xd);
379
-
380
378
  switch (rxn->node->type) {
381
379
  case XML_DOCUMENT_NODE:
382
380
  #ifdef LIBXML_DOCB_ENABLED
@@ -402,10 +400,10 @@ ruby_xml_node_doc(VALUE self) {
402
400
  if (doc == NULL)
403
401
  return(Qnil);
404
402
 
405
- docobj = ruby_xml_document_new(cXMLDocument, doc);
406
- Data_Get_Struct(docobj, ruby_xml_document, rxd);
407
- rxd->is_ptr = 1;
408
- return(docobj);
403
+ if ( doc->_private == NULL )
404
+ rb_raise(rb_eRuntimeError,"existing document object has no ruby-instance");
405
+
406
+ return (VALUE)doc->_private;
409
407
  }
410
408
 
411
409
 
@@ -676,10 +674,10 @@ ruby_xml_node_find_first(int argc, VALUE *argv, VALUE self) {
676
674
 
677
675
  switch(rxnset->node_set->nodeTab[0]->type) {
678
676
  case XML_ATTRIBUTE_NODE:
679
- nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[0]);
677
+ nodeobj = ruby_xml_attr_wrap(cXMLAttr, (xmlAttrPtr)rxnset->node_set->nodeTab[0]);
680
678
  break;
681
679
  default:
682
- nodeobj = ruby_xml_node_new_ptr(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]);
680
+ nodeobj = ruby_xml_node2_wrap(cXMLNode, rxnset->node_set->nodeTab[0]);
683
681
  }
684
682
 
685
683
  return(nodeobj);
@@ -702,25 +700,6 @@ ruby_xml_node_fragment_q(VALUE self) {
702
700
  return(Qfalse);
703
701
  }
704
702
 
705
-
706
- void ruby_xml_node_free(ruby_xml_node *rxn) {
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 (rxn->node->_private <= (void*)1) {
711
- // is null or last reference,
712
- xmlFreeNode(rxn->node);
713
- } else {
714
- // other pointers remain
715
- rxn->node->_private--;
716
- }
717
- }
718
-
719
- rxn->node = NULL;
720
- free(rxn);
721
- }
722
-
723
-
724
703
  /*
725
704
  * call-seq:
726
705
  * node.hash => fixnum
@@ -755,62 +734,6 @@ ruby_xml_node_html_doc_q(VALUE self) {
755
734
  return(Qfalse);
756
735
  }
757
736
 
758
-
759
- /*
760
- * call-seq:
761
- * XML::Node.new(name, content = nil) => node
762
- * XML::Node.new_element(name, content = nil) => node
763
- *
764
- * Create a new element node with the specified name, optionally setting
765
- * the node's content.
766
- */
767
- VALUE
768
- ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
769
- ruby_xml_node *rxn;
770
- VALUE name, node, str;
771
- xmlNodePtr newxn;
772
-
773
- str = Qnil;
774
-
775
- switch(argc) {
776
- case 2:
777
- switch (TYPE(str)) {
778
- case T_STRING:
779
- str = argv[1];
780
- break;
781
- default:
782
- str = rb_obj_as_string(argv[1]);
783
- if (NIL_P(str))
784
- Check_Type(str, T_STRING);
785
- break;
786
- }
787
-
788
- /* Intentionally fall through to case 1: as a way of setting up
789
- * the object. Sneaky, but effective. Probably should use a goto
790
- * instead. */
791
- case 1:
792
- name = check_string_or_symbol( argv[0] );
793
- newxn = xmlNewNode(NULL, (xmlChar*)StringValuePtr(name));
794
- node = ruby_xml_node_new(class, newxn);
795
-
796
- Data_Get_Struct(node, ruby_xml_node, rxn);
797
-
798
- /* TODO How would this happen? Shouldn't we raise on it anyway? */
799
- if (rxn->node == NULL)
800
- return(Qnil);
801
-
802
- if (!NIL_P(str))
803
- ruby_xml_node_content_set(node, str);
804
-
805
- break;
806
-
807
- default:
808
- rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
809
- }
810
-
811
- return(node);
812
- }
813
-
814
737
  /*
815
738
  * call-seq:
816
739
  * XML::Node.new_cdata(content = nil) => node
@@ -819,11 +742,9 @@ ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
819
742
  * the node's content.
820
743
  */
821
744
  VALUE
822
- ruby_xml_node_cdata_initialize(int argc, VALUE *argv, VALUE class) {
823
- xmlNode *xnode;
824
- VALUE node, str;
825
-
826
- str = Qnil;
745
+ ruby_xml_node_new_cdata(int argc, VALUE *argv, VALUE class) {
746
+ xmlNodePtr xnode;
747
+ VALUE node, str=Qnil;
827
748
 
828
749
  switch(argc) {
829
750
  case 1:
@@ -838,15 +759,14 @@ ruby_xml_node_cdata_initialize(int argc, VALUE *argv, VALUE class) {
838
759
  if (xnode == NULL)
839
760
  return(Qnil);
840
761
 
841
- node = ruby_xml_node_new(class, xnode);
842
-
843
- break;
762
+ return ruby_xml_node2_wrap(class,xnode);
844
763
 
845
764
  default:
846
765
  rb_raise(rb_eArgError, "wrong number of arguments (1)");
847
766
  }
848
767
 
849
- return(node);
768
+ // not reached
769
+ return(Qnil);
850
770
  }
851
771
 
852
772
 
@@ -859,11 +779,9 @@ ruby_xml_node_cdata_initialize(int argc, VALUE *argv, VALUE class) {
859
779
  *
860
780
  */
861
781
  VALUE
862
- ruby_xml_node_comment_initialize(int argc, VALUE *argv, VALUE class) {
863
- xmlNode *xnode;
864
- VALUE node, str;
865
-
866
- str = Qnil;
782
+ ruby_xml_node_new_comment(int argc, VALUE *argv, VALUE class) {
783
+ xmlNodePtr xnode;
784
+ VALUE node, str=Qnil;
867
785
 
868
786
  switch(argc) {
869
787
  case 1:
@@ -879,15 +797,14 @@ ruby_xml_node_comment_initialize(int argc, VALUE *argv, VALUE class) {
879
797
  if (xnode == NULL)
880
798
  return(Qnil);
881
799
 
882
- node = ruby_xml_node_new(class, xnode);
883
-
884
- break;
800
+ return ruby_xml_node2_wrap(class,xnode);
885
801
 
886
802
  default:
887
803
  rb_raise(rb_eArgError, "wrong number of arguments (1)");
888
804
  }
889
805
 
890
- return(node);
806
+ // not reached
807
+ return(Qnil);
891
808
  }
892
809
 
893
810
 
@@ -974,7 +891,7 @@ ruby_xml_node_last_get(VALUE self) {
974
891
  if (node == NULL)
975
892
  return(Qnil);
976
893
  else
977
- return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
894
+ return(ruby_xml_node2_wrap(cXMLNode, node));
978
895
  }
979
896
 
980
897
 
@@ -1056,12 +973,10 @@ ruby_xml_node_line_num(VALUE self) {
1056
973
  VALUE
1057
974
  ruby_xml_node_xlink_q(VALUE self) {
1058
975
  ruby_xml_node *node;
1059
- ruby_xml_document *doc;
1060
976
  xlinkType xlt;
1061
977
 
1062
978
  Data_Get_Struct(self, ruby_xml_node, node);
1063
- Data_Get_Struct(node->xd, ruby_xml_document, doc);
1064
- xlt = xlinkIsLink(doc->doc, node->node);
979
+ xlt = xlinkIsLink(node->node->doc, node->node);
1065
980
 
1066
981
  if (xlt == XLINK_TYPE_NONE)
1067
982
  return(Qfalse);
@@ -1081,12 +996,11 @@ ruby_xml_node_xlink_q(VALUE self) {
1081
996
  VALUE
1082
997
  ruby_xml_node_xlink_type(VALUE self) {
1083
998
  ruby_xml_node *node;
1084
- ruby_xml_document *doc;
999
+ ruby_xml_document_t *doc;
1085
1000
  xlinkType xlt;
1086
1001
 
1087
1002
  Data_Get_Struct(self, ruby_xml_node, node);
1088
- Data_Get_Struct(node->xd, ruby_xml_document, doc);
1089
- xlt = xlinkIsLink(doc->doc, node->node);
1003
+ xlt = xlinkIsLink(node->node->doc, node->node);
1090
1004
 
1091
1005
  if (xlt == XLINK_TYPE_NONE)
1092
1006
  return(Qnil);
@@ -1106,12 +1020,11 @@ ruby_xml_node_xlink_type(VALUE self) {
1106
1020
  VALUE
1107
1021
  ruby_xml_node_xlink_type_name(VALUE self) {
1108
1022
  ruby_xml_node *node;
1109
- ruby_xml_document *doc;
1023
+ ruby_xml_document_t *doc;
1110
1024
  xlinkType xlt;
1111
1025
 
1112
1026
  Data_Get_Struct(self, ruby_xml_node, node);
1113
- Data_Get_Struct(node->xd, ruby_xml_document, doc);
1114
- xlt = xlinkIsLink(doc->doc, node->node);
1027
+ xlt = xlinkIsLink(node->node->doc, node->node);
1115
1028
 
1116
1029
  switch(xlt) {
1117
1030
  case XLINK_TYPE_NONE:
@@ -1127,14 +1040,6 @@ ruby_xml_node_xlink_type_name(VALUE self) {
1127
1040
  }
1128
1041
  }
1129
1042
 
1130
-
1131
- static void
1132
- ruby_xml_node_mark(ruby_xml_node *rxn) {
1133
- if (rxn == NULL) return;
1134
- if (!NIL_P(rxn->xd)) rb_gc_mark(rxn->xd);
1135
- }
1136
-
1137
-
1138
1043
  /*
1139
1044
  * call-seq:
1140
1045
  * node.name => "string"
@@ -1224,7 +1129,7 @@ ruby_xml_node_namespace_get(VALUE self) {
1224
1129
 
1225
1130
  arr = rb_ary_new();
1226
1131
  for (cur = nsList; *cur != NULL; cur++) {
1227
- ns = ruby_xml_ns_new2(cXMLNS, node->xd, *cur);
1132
+ ns = ruby_xml_ns_new2(cXMLNS, ruby_xml_document_wrap(cXMLDocument,node->node->doc), *cur);
1228
1133
  if (ns == Qnil)
1229
1134
  continue;
1230
1135
  else
@@ -1250,7 +1155,9 @@ ruby_xml_node_namespace_get_node(VALUE self) {
1250
1155
  if (node->node->ns == NULL)
1251
1156
  return(Qnil);
1252
1157
  else
1253
- return(ruby_xml_ns_new2(cXMLNS, node->xd, node->node->ns));
1158
+ return ruby_xml_ns_new2(cXMLNS,
1159
+ ruby_xml_document_wrap(cXMLDocument,node->node->doc),
1160
+ node->node->ns);
1254
1161
  }
1255
1162
 
1256
1163
  // TODO namespace_set can take varargs (in fact, must if used
@@ -1308,7 +1215,7 @@ ruby_xml_node_namespace_set(int argc, VALUE *argv, VALUE self) {
1308
1215
  if (ns == NULL)
1309
1216
  rb_raise(eXMLNodeSetNamespace, "unable to set the namespace");
1310
1217
  else
1311
- return(ruby_xml_ns_new2(cXMLNS, rxn->xd, ns));
1218
+ return ruby_xml_ns_new2(cXMLNS, ruby_xml_document_wrap(cXMLDocument,rxn->node->doc), ns);
1312
1219
  break;
1313
1220
 
1314
1221
  default:
@@ -1337,87 +1244,154 @@ ruby_xml_node_namespace_q(VALUE self) {
1337
1244
  return(Qfalse);
1338
1245
  }
1339
1246
 
1340
- /* TODO new_ptr and new3 are obsolete, should be consolidated */
1341
- VALUE
1342
- ruby_xml_node_new(VALUE class, xmlNodePtr node) {
1343
- return ruby_xml_node_new_ptr(class, Qnil, node);
1247
+ /*
1248
+ * memory2 implementation: xmlNode->_private holds a reference
1249
+ * to the wrapping ruby object VALUE when there is one.
1250
+ * traversal for marking is upward, and top levels are marked
1251
+ * through and lower level mark entry.
1252
+ *
1253
+ * All ruby retrieval for an xml
1254
+ * node will result in the same ruby instance. When all handles to them
1255
+ * go out of scope, then free gets called and _private is set to NULL.
1256
+ * If the xmlNode has no parent or document, then call xmlFree.
1257
+ */
1258
+ void
1259
+ ruby_xml_node2_free(ruby_xml_node *rxn) {
1260
+
1261
+ if (rxn->node == NULL ) return;
1262
+
1263
+ if (rxn->node->parent == NULL && rxn->node->doc == NULL ) {
1264
+ #ifdef NODE_DEBUG
1265
+ fprintf(stderr,"free rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)rxn->node,(long)rxn->node->_private);
1266
+ #endif
1267
+ rxn->node->_private=NULL;
1268
+ xmlFreeNode(rxn->node);
1269
+ }
1270
+
1271
+ rxn->node=NULL;
1272
+ // fprintf(stderr,"%0x ",(long)rxn);
1273
+ free(rxn);
1344
1274
  }
1345
1275
 
1276
+ void
1277
+ ruby_xml_node2_mark(ruby_xml_node *rxn) {
1278
+ xmlNodePtr node;
1279
+ if (rxn->node == NULL ) return;
1346
1280
 
1347
- VALUE
1348
- ruby_xml_node_new_ptr(VALUE class, VALUE xd, xmlNodePtr node) {
1349
- return ruby_xml_node_new3(class, xd, node, 1);
1281
+ if (rxn->node->_private == NULL ) {
1282
+ rb_warning("XmlNode is not bound! (%s:%d)",
1283
+ __FILE__,__LINE__);
1284
+ return;
1285
+ }
1286
+
1287
+ if (rxn->node->doc != NULL ) {
1288
+ if (rxn->node->doc->_private == NULL )
1289
+ rb_warning("XmlNode Doc is not bound! (%s:%d)",
1290
+ __FILE__,__LINE__);
1291
+ else {
1292
+ rb_gc_mark((VALUE)rxn->node->doc->_private);
1293
+ #ifdef NODE_DEBUG
1294
+ fprintf(stderr,"mark rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)rxn->node,(long)rxn->node->_private);
1295
+ #endif
1296
+ }
1297
+ } else if (rxn->node->parent != NULL ) {
1298
+ if (rxn->node->parent->_private == NULL )
1299
+ rb_warning("XmlNode Parent is not bound! (%s:%d)",
1300
+ __FILE__,__LINE__);
1301
+ node=rxn->node;
1302
+ while (node->parent != NULL )
1303
+ node=node->parent;
1304
+ if (node->_private != NULL) {
1305
+ rb_gc_mark((VALUE)node->_private);
1306
+ #ifdef NODE_DEBUG
1307
+ fprintf(stderr,"mark rxn=0x%x xn=0x%x o=0x%x\n",(long)0,(long)node,(long)node->_private);
1308
+ #endif
1309
+ }
1310
+ }
1350
1311
  }
1351
1312
 
1313
+ VALUE
1314
+ ruby_xml_node2_wrap(VALUE class, xmlNodePtr xnode)
1315
+ {
1316
+ VALUE obj;
1317
+ ruby_xml_node *rxn;
1352
1318
 
1353
- /* TODO ptr arg is obsolete, should be removed */
1319
+ // This node is already wrapped
1320
+ if (xnode->_private != NULL)
1321
+ return (VALUE)xnode->_private;
1322
+
1323
+ obj=Data_Make_Struct(class,ruby_xml_node,ruby_xml_node2_mark,
1324
+ ruby_xml_node2_free,rxn);
1325
+
1326
+ rxn->node=xnode;
1327
+ xnode->_private=(void*)obj;
1328
+ #ifdef NODE_DEBUG
1329
+ fprintf(stderr,"wrap rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)xnode,(long)obj);
1330
+ #endif
1331
+ return obj;
1332
+ }
1354
1333
 
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
- */
1393
1334
  VALUE
1394
- ruby_xml_node_new3(VALUE class, VALUE xd, xmlNodePtr node, int ptr) {
1335
+ ruby_xml_node2_new_native(VALUE class, VALUE ns, VALUE name)
1336
+ {
1337
+ VALUE obj;
1338
+ xmlNodePtr xnode;
1339
+ xmlNsPtr xns=NULL;
1395
1340
  ruby_xml_node *rxn;
1396
- rxn = ALLOC(ruby_xml_node);
1397
1341
 
1398
- rxn->node = node;
1399
- if (node->_private) {
1400
- node->_private++;
1401
- } else {
1402
- node->_private = (void*)1;
1403
- }
1404
-
1405
- if (NIL_P(xd)) {
1406
- rxn->xd = Qnil;
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
-
1413
- rxn->xd = xd;
1414
- rxn->node->doc = xdoc->doc;
1342
+ if ( ! NIL_P(ns) ) {
1343
+ Data_Get_Struct(ns,xmlNs,xns);
1415
1344
  }
1345
+ xnode=xmlNewNode(xns,(xmlChar*)StringValuePtr(name));
1346
+ xnode->_private=NULL;
1416
1347
 
1417
- return(Data_Wrap_Struct(class, ruby_xml_node_mark,
1418
- ruby_xml_node_free, rxn));
1348
+ obj=
1349
+ ruby_xml_node2_wrap(class,xnode);
1350
+
1351
+ rb_obj_call_init(obj,0,NULL);
1352
+ return obj;
1419
1353
  }
1420
1354
 
1355
+ VALUE
1356
+ ruby_xml_node2_new_string(VALUE class, VALUE ns, VALUE name, VALUE val)
1357
+ {
1358
+ VALUE obj;
1359
+ char* value;
1360
+ obj=ruby_xml_node2_new_native(class,ns,name);
1361
+ if ( ! NIL_P(val) ) {
1362
+ if ( TYPE(val) != T_STRING )
1363
+ val=rb_obj_as_string(val);
1364
+ ruby_xml_node_content_set(obj,val);
1365
+ }
1366
+ return obj;
1367
+ }
1368
+ /*
1369
+ * call-seq:
1370
+ * XML::Node.new(name, content = nil) => node
1371
+ * XML::Node.new_element(name, content = nil) => node
1372
+ *
1373
+ * Create a new element node with the specified name, optionally setting
1374
+ * the node's content.
1375
+ * backward compatibility for <.5 new
1376
+ */
1377
+ VALUE
1378
+ ruby_xml_node2_new_string_bc(int argc, VALUE *argv, VALUE class)
1379
+ {
1380
+ VALUE content=Qnil,name=Qnil,rxnode;
1381
+ switch(argc) {
1382
+ case 2:
1383
+ content=argv[1];
1384
+ if ( TYPE(content) != T_STRING)
1385
+ content=rb_obj_as_string(content);
1386
+
1387
+ case 1:
1388
+ name=check_string_or_symbol( argv[0] );
1389
+ return ruby_xml_node2_new_string(class,Qnil,name,content);
1390
+
1391
+ default:
1392
+ rb_raise(rb_eArgError, "wrong number of arguments (1 or 2) given %d",argc);
1393
+ }
1394
+ }
1421
1395
 
1422
1396
  /*
1423
1397
  * call-seq:
@@ -1459,7 +1433,7 @@ ruby_xml_node_next_get(VALUE self) {
1459
1433
  if (node == NULL) {
1460
1434
  return(Qnil);
1461
1435
  } else {
1462
- return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
1436
+ return(ruby_xml_node2_wrap(cXMLNode, node));
1463
1437
  }
1464
1438
  }
1465
1439
 
@@ -1529,7 +1503,7 @@ ruby_xml_node_next_set(VALUE self, VALUE rnode) {
1529
1503
  if (ret == NULL)
1530
1504
  rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
1531
1505
 
1532
- return(ruby_xml_node_new_ptr(cXMLNode, pnode->xd, ret));
1506
+ return(ruby_xml_node2_wrap(cXMLNode, ret));
1533
1507
  }
1534
1508
 
1535
1509
 
@@ -1580,7 +1554,7 @@ ruby_xml_node_ns_def_get(VALUE self) {
1580
1554
  if (rxn->node->nsDef == NULL)
1581
1555
  return(Qnil);
1582
1556
  else
1583
- return(ruby_xml_ns_new2(cXMLNS, rxn->xd, rxn->node->nsDef));
1557
+ return(ruby_xml_ns_new2(cXMLNS, ruby_xml_document_wrap(cXMLDocument,rxn->node->doc), rxn->node->nsDef));
1584
1558
  }
1585
1559
 
1586
1560
 
@@ -1642,7 +1616,7 @@ ruby_xml_node_parent_get(VALUE self) {
1642
1616
  if (node == NULL)
1643
1617
  return(Qnil);
1644
1618
  else
1645
- return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
1619
+ return(ruby_xml_node2_wrap(cXMLNode, node));
1646
1620
  }
1647
1621
 
1648
1622
 
@@ -1775,7 +1749,7 @@ ruby_xml_node_prev_get(VALUE self) {
1775
1749
  if (node == NULL)
1776
1750
  return(Qnil);
1777
1751
  else
1778
- return(ruby_xml_node_new_ptr(cXMLNode, rxn->xd, node));
1752
+ return(ruby_xml_node2_wrap(cXMLNode, node));
1779
1753
  }
1780
1754
 
1781
1755
 
@@ -1840,7 +1814,7 @@ ruby_xml_node_prev_set(VALUE self, VALUE rnode) {
1840
1814
  if (ret == NULL)
1841
1815
  rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
1842
1816
 
1843
- return(ruby_xml_node_new_ptr(cXMLNode, pnode->xd, ret));
1817
+ return(ruby_xml_node2_wrap(cXMLNode, ret));
1844
1818
  }
1845
1819
 
1846
1820
 
@@ -1901,18 +1875,15 @@ ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) {
1901
1875
  if (attr == NULL)
1902
1876
  return(Qnil);
1903
1877
  }
1904
- return(ruby_xml_attr_new(cXMLAttr, node->xd, attr));
1878
+ return(ruby_xml_attr_new(cXMLAttr, attr));
1905
1879
  }
1906
1880
 
1907
1881
 
1908
1882
  /*
1909
1883
  * call-seq:
1910
- * node.properties => attributes or nil
1884
+ * node.properties => attributes
1911
1885
  *
1912
- * Returns the first +XML::Attr+ for this node. Use the
1913
- * +name+ and +value+ methods to obtain the attribute's
1914
- * data, and the +prev+ and +next+ methods to
1915
- * navigate the property list.
1886
+ * Returns the +XML::Attr+ for this node.
1916
1887
  */
1917
1888
  VALUE
1918
1889
  ruby_xml_node_properties_get(VALUE self) {
@@ -1924,10 +1895,10 @@ ruby_xml_node_properties_get(VALUE self) {
1924
1895
  if (node->node->type == XML_ELEMENT_NODE) {
1925
1896
  attr = node->node->properties;
1926
1897
 
1927
- if (attr == NULL) {
1928
- return(Qnil);
1898
+ if (attr == NULL) {
1899
+ return(Qnil);
1929
1900
  } else {
1930
- return(ruby_xml_attr_new2(cXMLAttr, node->xd, attr));
1901
+ return(ruby_xml_attr_wrap(cXMLAttr, attr));
1931
1902
  }
1932
1903
  } else {
1933
1904
  return(Qnil);
@@ -1976,14 +1947,12 @@ ruby_xml_node_remove_ex(VALUE self) {
1976
1947
  */
1977
1948
  VALUE
1978
1949
  ruby_xml_node_search_href(VALUE self, VALUE href) {
1979
- ruby_xml_document *doc;
1980
1950
  ruby_xml_node *node;
1981
1951
 
1982
1952
  Check_Type(href, T_STRING);
1983
1953
  Data_Get_Struct(self, ruby_xml_node, node);
1984
- Data_Get_Struct(node->xd, ruby_xml_document, doc);
1985
- return(ruby_xml_ns_new2(cXMLNS, node->xd,
1986
- xmlSearchNsByHref(doc->doc, node->node,
1954
+ return(ruby_xml_ns_new2(cXMLNS, ruby_xml_document_wrap(cXMLDocument,node->node->doc),
1955
+ xmlSearchNsByHref(node->node->doc, node->node,
1987
1956
  (xmlChar*)StringValuePtr(href))));
1988
1957
  }
1989
1958
 
@@ -1996,27 +1965,14 @@ ruby_xml_node_search_href(VALUE self, VALUE href) {
1996
1965
  */
1997
1966
  VALUE
1998
1967
  ruby_xml_node_search_ns(VALUE self, VALUE ns) {
1999
- ruby_xml_document *doc;
2000
1968
  ruby_xml_node *node;
2001
1969
 
2002
1970
  Check_Type(ns, T_STRING);
2003
1971
  Data_Get_Struct(self, ruby_xml_node, node);
2004
- Data_Get_Struct(node->xd, ruby_xml_document, doc);
2005
- return(ruby_xml_ns_new2(cXMLNS, node->xd,
2006
- xmlSearchNs(doc->doc, node->node,
2007
- (xmlChar*)StringValuePtr(ns))));
2008
- }
2009
-
2010
-
2011
- /* TODO Obsolete, remove */
2012
- VALUE
2013
- ruby_xml_node_set_ptr(VALUE node, int is_ptr) {
2014
- /*
2015
- ruby_xml_node *rxn;
2016
- Data_Get_Struct(node, ruby_xml_node, rxn);
2017
- rxn->is_ptr = is_ptr;
2018
- */
2019
- return(Qtrue);
1972
+ return(ruby_xml_ns_new2(cXMLNS,
1973
+ ruby_xml_document_wrap(cXMLDocument,node->node->doc),
1974
+ xmlSearchNs(node->node->doc, node->node,
1975
+ (xmlChar*)StringValuePtr(ns))));
2020
1976
  }
2021
1977
 
2022
1978
 
@@ -2030,6 +1986,7 @@ VALUE
2030
1986
  ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
2031
1987
  ruby_xml_node *cnode, *pnode;
2032
1988
  xmlNodePtr ret;
1989
+ VALUE obj;
2033
1990
 
2034
1991
  if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
2035
1992
  rb_raise(rb_eTypeError, "Must pass an XML::Node object");
@@ -2040,8 +1997,12 @@ ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
2040
1997
  ret = xmlAddSibling(pnode->node, cnode->node);
2041
1998
  if (ret == NULL)
2042
1999
  rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
2000
+ if (ret->_private==NULL)
2001
+ obj=ruby_xml_node2_wrap(cXMLNode,ret);
2002
+ else
2003
+ obj=(VALUE)ret->_private;
2043
2004
 
2044
- return(ruby_xml_node_new_ptr(cXMLNode, pnode->xd, ret));
2005
+ return obj;
2045
2006
  }
2046
2007
 
2047
2008
 
@@ -2241,16 +2202,17 @@ VALUE
2241
2202
  ruby_xml_node_copy(VALUE self, VALUE deep) {
2242
2203
  ruby_xml_node *rxn;
2243
2204
  xmlNode *copy;
2244
-
2205
+ VALUE obj;
2206
+
2245
2207
  Data_Get_Struct(self, ruby_xml_node, rxn);
2246
2208
  copy = xmlCopyNode( rxn->node, ((deep==Qnil)||(deep==Qfalse))?0:1 );
2247
- copy->_private = (void*)0;
2248
-
2249
- if (copy == NULL) {
2209
+
2210
+ if (copy == NULL)
2250
2211
  return Qnil;
2251
- } else {
2252
- return(ruby_xml_node_new(cXMLNode, copy));
2253
- }
2212
+
2213
+ obj=ruby_xml_node2_wrap(cXMLNode,copy);
2214
+ copy->_private = (void*) obj;
2215
+ return obj;
2254
2216
  }
2255
2217
 
2256
2218
 
@@ -2261,10 +2223,14 @@ ruby_xml_node_copy(VALUE self, VALUE deep) {
2261
2223
 
2262
2224
  void
2263
2225
  ruby_init_xml_node(void) {
2226
+ VALUE singleton;
2227
+
2264
2228
  cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
2265
2229
  eXMLNodeSetNamespace = rb_define_class_under(cXMLNode, "SetNamespace", eXMLError);
2266
2230
  eXMLNodeFailedModify = rb_define_class_under(cXMLNode, "FailedModify", eXMLError);
2267
2231
  eXMLNodeUnknownType = rb_define_class_under(cXMLNode, "UnknownType", eXMLError);
2232
+
2233
+ singleton = rb_singleton_class(cXMLNode);
2268
2234
 
2269
2235
  rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
2270
2236
  rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
@@ -2281,11 +2247,11 @@ ruby_init_xml_node(void) {
2281
2247
  rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
2282
2248
  rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
2283
2249
 
2284
- rb_define_singleton_method(cXMLNode, "new", ruby_xml_node_initialize, -1);
2285
- rb_define_singleton_method(cXMLNode, "new_cdata", ruby_xml_node_cdata_initialize, -1);
2286
- rb_define_singleton_method(cXMLNode, "new_comment", ruby_xml_node_comment_initialize, -1);
2250
+ rb_define_singleton_method(cXMLNode, "new2", ruby_xml_node2_new_native, 2);
2251
+ rb_define_singleton_method(cXMLNode, "new", ruby_xml_node2_new_string_bc, -1);
2252
+ rb_define_singleton_method(cXMLNode, "new_cdata", ruby_xml_node_new_cdata, -1);
2253
+ rb_define_singleton_method(cXMLNode, "new_comment", ruby_xml_node_new_comment, -1);
2287
2254
 
2288
- VALUE singleton = rb_singleton_class(cXMLNode);
2289
2255
  rb_define_alias(singleton, "new_element", "new");
2290
2256
 
2291
2257
  rb_define_method(cXMLNode, "<<", ruby_xml_node_content_add, 1);