libxml-ruby 0.9.8-x86-mswin32-60 → 0.9.9-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.
Files changed (98) hide show
  1. data/CHANGES +41 -1
  2. data/LICENSE +3 -4
  3. data/README +37 -24
  4. data/Rakefile +2 -2
  5. data/ext/libxml/extconf.rb +31 -12
  6. data/ext/libxml/libxml.c +56 -858
  7. data/ext/libxml/ruby_libxml.h +93 -96
  8. data/ext/libxml/ruby_xml.c +855 -0
  9. data/ext/libxml/ruby_xml.h +9 -0
  10. data/ext/libxml/ruby_xml_attr.c +3 -9
  11. data/ext/libxml/ruby_xml_attr.h +2 -2
  12. data/ext/libxml/ruby_xml_attr_decl.c +2 -8
  13. data/ext/libxml/ruby_xml_attr_decl.h +1 -1
  14. data/ext/libxml/ruby_xml_attributes.c +6 -8
  15. data/ext/libxml/ruby_xml_attributes.h +1 -1
  16. data/ext/libxml/ruby_xml_document.c +915 -895
  17. data/ext/libxml/ruby_xml_document.h +2 -2
  18. data/ext/libxml/ruby_xml_dtd.c +257 -136
  19. data/ext/libxml/ruby_xml_dtd.h +1 -1
  20. data/ext/libxml/ruby_xml_encoding.c +55 -37
  21. data/ext/libxml/ruby_xml_encoding.h +1 -1
  22. data/ext/libxml/ruby_xml_error.c +526 -1058
  23. data/ext/libxml/ruby_xml_error.h +1 -1
  24. data/ext/libxml/ruby_xml_html_parser.c +2 -8
  25. data/ext/libxml/ruby_xml_html_parser.h +2 -2
  26. data/ext/libxml/ruby_xml_html_parser_context.c +175 -145
  27. data/ext/libxml/ruby_xml_html_parser_context.h +1 -1
  28. data/ext/libxml/ruby_xml_html_parser_options.c +12 -20
  29. data/ext/libxml/ruby_xml_html_parser_options.h +1 -1
  30. data/ext/libxml/ruby_xml_input_cbg.c +2 -8
  31. data/ext/libxml/ruby_xml_input_cbg.h +1 -1
  32. data/ext/libxml/ruby_xml_namespace.c +2 -8
  33. data/ext/libxml/ruby_xml_namespace.h +2 -2
  34. data/ext/libxml/ruby_xml_namespaces.c +1 -9
  35. data/ext/libxml/ruby_xml_namespaces.h +1 -1
  36. data/ext/libxml/ruby_xml_node.c +182 -121
  37. data/ext/libxml/ruby_xml_node.h +2 -2
  38. data/ext/libxml/ruby_xml_parser.c +2 -8
  39. data/ext/libxml/ruby_xml_parser.h +2 -2
  40. data/ext/libxml/ruby_xml_parser_context.c +952 -901
  41. data/ext/libxml/ruby_xml_parser_context.h +2 -2
  42. data/ext/libxml/ruby_xml_parser_options.c +2 -9
  43. data/ext/libxml/ruby_xml_parser_options.h +1 -1
  44. data/ext/libxml/ruby_xml_reader.c +1002 -993
  45. data/ext/libxml/ruby_xml_reader.h +1 -1
  46. data/ext/libxml/ruby_xml_relaxng.c +1 -7
  47. data/ext/libxml/ruby_xml_relaxng.h +1 -1
  48. data/ext/libxml/ruby_xml_sax2_handler.c +2 -2
  49. data/ext/libxml/ruby_xml_sax2_handler.h +1 -1
  50. data/ext/libxml/ruby_xml_sax_parser.c +2 -8
  51. data/ext/libxml/ruby_xml_sax_parser.h +2 -2
  52. data/ext/libxml/ruby_xml_schema.c +1 -7
  53. data/ext/libxml/ruby_xml_schema.h +1 -1
  54. data/ext/libxml/{version.h → ruby_xml_version.h} +2 -2
  55. data/ext/libxml/ruby_xml_xinclude.c +2 -8
  56. data/ext/libxml/ruby_xml_xinclude.h +2 -2
  57. data/ext/libxml/ruby_xml_xpath.c +17 -18
  58. data/ext/libxml/ruby_xml_xpath.h +2 -2
  59. data/ext/libxml/ruby_xml_xpath_context.c +387 -389
  60. data/ext/libxml/ruby_xml_xpath_context.h +2 -2
  61. data/ext/libxml/ruby_xml_xpath_expression.c +18 -8
  62. data/ext/libxml/ruby_xml_xpath_expression.h +1 -1
  63. data/ext/libxml/ruby_xml_xpath_object.c +19 -8
  64. data/ext/libxml/ruby_xml_xpath_object.h +1 -1
  65. data/ext/libxml/ruby_xml_xpointer.c +2 -8
  66. data/ext/libxml/ruby_xml_xpointer.h +2 -2
  67. data/ext/mingw/libxml_ruby.dll.a +0 -0
  68. data/ext/mingw/libxml_ruby.so +0 -0
  69. data/ext/vc/libxml_ruby.sln +7 -1
  70. data/lib/libxml.rb +1 -12
  71. data/lib/libxml/attr.rb +0 -3
  72. data/lib/libxml/attr_decl.rb +0 -3
  73. data/lib/libxml/attributes.rb +0 -3
  74. data/lib/libxml/document.rb +31 -5
  75. data/lib/libxml/error.rb +8 -4
  76. data/lib/libxml/properties.rb +0 -5
  77. data/lib/libxml/sax_callbacks.rb +30 -19
  78. data/lib/libxml/tree.rb +0 -1
  79. data/lib/libxml/xpath_object.rb +0 -13
  80. data/test/model/definition.dtd +8 -0
  81. data/test/tc_attributes.rb +4 -1
  82. data/test/tc_document.rb +16 -0
  83. data/test/tc_dtd.rb +30 -2
  84. data/test/tc_html_parser.rb +55 -10
  85. data/test/tc_node.rb +67 -1
  86. data/test/tc_node_edit.rb +26 -6
  87. data/test/tc_node_text.rb +41 -23
  88. data/test/tc_parser.rb +50 -0
  89. data/test/tc_reader.rb +15 -0
  90. data/test/tc_relaxng.rb +1 -1
  91. data/test/tc_sax_parser.rb +37 -5
  92. data/test/tc_schema.rb +1 -1
  93. data/test/tc_xpath.rb +1 -0
  94. data/test/tc_xpath_expression.rb +4 -2
  95. metadata +6 -6
  96. data/ext/libxml/ruby_xml_state.c +0 -51
  97. data/ext/libxml/ruby_xml_state.h +0 -11
  98. data/ext/vc/libxml_ruby.vcproj +0 -460
@@ -1,7 +1,7 @@
1
1
  #ifndef _INPUT_CBG_
2
2
  #define _INPUT_CBG_
3
3
 
4
- void ruby_init_input_callbacks(void);
4
+ void rxml_init_input_callbacks(void);
5
5
 
6
6
  typedef struct ic_doc_context {
7
7
  char *buffer;
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_namespace.c 740 2009-01-23 04:03:11Z cfis $ */
1
+ /* $Id: ruby_xml_namespace.c 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -158,13 +158,7 @@ static VALUE rxml_namespace_next(VALUE self)
158
158
  return (rxml_namespace_wrap(xns->next, NULL));
159
159
  }
160
160
 
161
- // Rdoc needs to know
162
- #ifdef RDOC_NEVER_DEFINED
163
- mLibXML = rb_define_module("LibXML");
164
- mXML = rb_define_module_under(mLibXML, "XML");
165
- #endif
166
-
167
- void ruby_init_xml_namespace(void)
161
+ void rxml_init_namespace(void)
168
162
  {
169
163
  cXMLNamespace = rb_define_class_under(mXML, "Namespace", rb_cObject);
170
164
  rb_define_alloc_func(cXMLNamespace, rxml_namespace_alloc);
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_namespace.h 739 2009-01-23 03:42:09Z cfis $ */
1
+ /* $Id: ruby_xml_namespace.h 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -7,6 +7,6 @@
7
7
 
8
8
  extern VALUE cXMLNamespace;
9
9
 
10
- void ruby_init_xml_namespace(void);
10
+ void rxml_init_namespace(void);
11
11
  VALUE rxml_namespace_wrap(xmlNsPtr xns, RUBY_DATA_FUNC freeFunc);
12
12
  #endif
@@ -277,15 +277,7 @@ static VALUE rxml_namespaces_node_get(VALUE self)
277
277
  return rxml_node_wrap(xnode);
278
278
  }
279
279
 
280
-
281
-
282
- // Rdoc needs to know
283
- #ifdef RDOC_NEVER_DEFINED
284
- mLibXML = rb_define_module("LibXML");
285
- mXML = rb_define_module_under(mLibXML, "XML");
286
- #endif
287
-
288
- void ruby_init_xml_namespaces(void)
280
+ void rxml_init_namespaces(void)
289
281
  {
290
282
  cXMLNamespaces = rb_define_class_under(mXML, "Namespaces", rb_cObject);
291
283
  rb_include_module(cXMLNamespaces, rb_mEnumerable);
@@ -7,5 +7,5 @@
7
7
 
8
8
  extern VALUE cXMLNamespaces;
9
9
 
10
- void ruby_init_xml_namespaces(void);
10
+ void rxml_init_namespaces(void);
11
11
  #endif
@@ -3,9 +3,6 @@
3
3
 
4
4
  VALUE cXMLNode;
5
5
 
6
- static VALUE kXMLStringText;
7
- static VALUE kXMLStringTextNoenc;
8
-
9
6
  /* Document-class: LibXML::XML::Node
10
7
  *
11
8
  * Nodes are the primary objects that make up an XML document.
@@ -29,23 +26,48 @@ VALUE check_string_or_symbol(VALUE val)
29
26
  return rb_obj_as_string(val);
30
27
  }
31
28
 
32
- /*
33
- * memory2 implementation: xmlNode->_private holds a reference
34
- * to the wrapping ruby object VALUE when there is one.
35
- * traversal for marking is upward, and top levels are marked
36
- * through and lower level mark entry.
29
+ /* Memory management:
30
+ *
31
+ * The bindings create a one-to-one mapping between libxml nodes
32
+ * and Ruby nodes. If a libxml node is wraped, its _private member
33
+ * is set with a reference to the Ruby object.
37
34
  *
38
- * All ruby retrieval for an xml
39
- * node will result in the same ruby instance. When all handles to them
40
- * go out of scope, then ruby_xfree gets called and _private is set to NULL.
41
- * If the xmlNode has no parent or document, then call xmlFree.
35
+ * When a libxml document or top level node is freed, it will free
36
+ * all its children. Thus Ruby is responsible for:
37
+ *
38
+ * * Using the mark function to keep alive any documents Ruby is
39
+ * referencing via the document or child nodes.
40
+ * * Using the mark function to keep alive any top level, free
41
+ * standing nodes Ruby is referencing via the node or its children.
42
+ *
43
+ * Ruby will always set a free function when wrapping a node. However,
44
+ * the bindings also register a callback that is invoked by libxml
45
+ * each time a node is freed. When the callback is called, the node's
46
+ * dfree member is set to NULL since Ruby no longer should free the node.
42
47
  */
48
+
49
+ void rxml_node_deregisterNode(xmlNodePtr xnode)
50
+ {
51
+ /* Has the node been wrapped and exposed to Ruby? */
52
+ if (xnode->_private)
53
+ {
54
+ /* Node was wrapped. Set the _private member to free and
55
+ then dislabe the dfree function so that Ruby will not
56
+ try to free the node a second time. */
57
+ VALUE node = (VALUE) xnode->_private;
58
+ RDATA(node)->dfree = NULL;
59
+ xnode->_private = NULL;
60
+ }
61
+ }
62
+
43
63
  void rxml_node_free(xmlNodePtr xnode)
44
64
  {
45
- /* Set _private to NULL so that we won't reuse the
46
- same, freed, Ruby wrapper object later.*/
65
+ /* The Ruby object that wraps the node no longer exists. */
47
66
  xnode->_private = NULL;
48
67
 
68
+ /* Only free nodes that are stand-alone, top level nodes.
69
+ If a node belongs to a document, or a parent node, then
70
+ the document or parent node will free thsi node. */
49
71
  if (xnode->doc == NULL && xnode->parent == NULL)
50
72
  xmlFreeNode(xnode);
51
73
  }
@@ -96,6 +118,9 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
96
118
  }
97
119
  else
98
120
  {
121
+ /* Assume Ruby is responsible for freeing this node. If libxml frees it
122
+ instead, the rxml_node_deregisterNode callback is executed, and
123
+ we set the free function to NULL. */
99
124
  VALUE node = Data_Wrap_Struct(cXMLNode, rxml_node_mark, rxml_node_free, xnode);
100
125
  xnode->_private = (void*) node;
101
126
  return node;
@@ -104,6 +129,7 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
104
129
 
105
130
  static VALUE rxml_node_alloc(VALUE klass)
106
131
  {
132
+ /* Ruby is responsible for freeing this node not libxml. */
107
133
  return Data_Wrap_Struct(klass, rxml_node_mark, rxml_node_free, NULL);
108
134
  }
109
135
 
@@ -381,34 +407,26 @@ static VALUE rxml_node_first_get(VALUE self)
381
407
  * underlying for child_set and child_add, difference being
382
408
  * former raises on implicit copy, latter does not.
383
409
  */
384
- static VALUE rxml_node_child_set_aux(VALUE self, VALUE rnode)
410
+ static VALUE rxml_node_child_set_aux(VALUE self, VALUE child)
385
411
  {
386
- xmlNodePtr pnode, chld, ret;
412
+ xmlNodePtr xnode, xchild, xresult;
387
413
 
388
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
414
+ if (rb_obj_is_kind_of(child, cXMLNode) == Qfalse)
389
415
  rb_raise(rb_eTypeError, "Must pass an XML::Node object");
390
416
 
391
- Data_Get_Struct(self, xmlNode, pnode);
392
- Data_Get_Struct(rnode, xmlNode, chld);
417
+ Data_Get_Struct(self, xmlNode, xnode);
418
+ Data_Get_Struct(child, xmlNode, xchild);
393
419
 
394
- if (chld->parent != NULL || chld->doc != NULL)
395
- rb_raise(
396
- rb_eRuntimeError,
397
- "Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
420
+ if (xchild->parent != NULL || xchild->doc != NULL)
421
+ rb_raise(rb_eRuntimeError,
422
+ "Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
398
423
 
399
- ret = xmlAddChild(pnode, chld);
400
- if (ret == NULL)
401
- {
424
+ xresult = xmlAddChild(xnode, xchild);
425
+
426
+ if (!xresult)
402
427
  rxml_raise(&xmlLastError);
403
- }
404
- else if (ret == chld)
405
- {
406
- /* child was added whole to parent and we need to return it as a new object */
407
- return rxml_node_wrap(chld);
408
- }
409
- /* else */
410
- /* If it was a text node, then ret should be parent->last, so we will just return ret. */
411
- return rxml_node_wrap(ret);
428
+
429
+ return rxml_node_wrap(xresult);
412
430
  }
413
431
 
414
432
  /*
@@ -603,15 +621,19 @@ static VALUE rxml_node_to_s(int argc, VALUE *argv, VALUE self)
603
621
  static VALUE rxml_node_each(VALUE self)
604
622
  {
605
623
  xmlNodePtr xnode;
606
- xmlNodePtr xchild;
624
+ xmlNodePtr xcurrent;
607
625
  Data_Get_Struct(self, xmlNode, xnode);
608
626
 
609
- xchild = xnode->children;
627
+ xcurrent = xnode->children;
610
628
 
611
- while (xchild)
629
+ while (xcurrent)
612
630
  {
613
- rb_yield(rxml_node_wrap(xchild));
614
- xchild = xchild->next;
631
+ /* The user could remove this node, so first stache
632
+ away the next node. */
633
+ xmlNodePtr xnext = xcurrent->next;
634
+
635
+ rb_yield(rxml_node_wrap(xcurrent));
636
+ xcurrent = xnext;
615
637
  }
616
638
  return Qnil;
617
639
  }
@@ -868,10 +890,6 @@ static VALUE rxml_node_name_get(VALUE self)
868
890
 
869
891
  if (xnode->name == NULL)
870
892
  return (Qnil);
871
- else if (name == xmlStringText)
872
- return (kXMLStringText);
873
- else if (name == xmlStringTextNoenc)
874
- return (kXMLStringTextNoenc);
875
893
  else
876
894
  return (rb_str_new2((const char*) name));
877
895
  }
@@ -891,14 +909,9 @@ static VALUE rxml_node_name_set(VALUE self, VALUE name)
891
909
  Data_Get_Struct(self, xmlNode, xnode);
892
910
  xname = (const xmlChar*)StringValuePtr(name);
893
911
 
894
- if (xnode->type != XML_TEXT_NODE)
895
- xmlNodeSetName(xnode, xname);
896
- else if (xname == xmlStringText) /* compare addresses instead of string contents. */
897
- xnode->name = xmlStringText;
898
- else if (xname == xmlStringTextNoenc) /* compare addresses instead of string contents. */
899
- xnode->name = xmlStringTextNoenc;
900
-
901
912
  /* Note: calling xmlNodeSetName() for a text node is ignored by libXML. */
913
+ xmlNodeSetName(xnode, xname);
914
+
902
915
  return (Qtrue);
903
916
  }
904
917
 
@@ -926,21 +939,21 @@ static VALUE rxml_node_next_get(VALUE self)
926
939
  *
927
940
  * Insert the specified node as this node's next sibling.
928
941
  */
929
- static VALUE rxml_node_next_set(VALUE self, VALUE rnode)
942
+ static VALUE rxml_node_next_set(VALUE self, VALUE next)
930
943
  {
931
- xmlNodePtr cnode, pnode, ret;
944
+ xmlNodePtr xnode, xnext, xresult;
932
945
 
933
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
946
+ if (rb_obj_is_kind_of(next, cXMLNode) == Qfalse)
934
947
  rb_raise(rb_eTypeError, "Must pass an XML::Node object");
935
948
 
936
- Data_Get_Struct(self, xmlNode, pnode);
937
- Data_Get_Struct(rnode, xmlNode, cnode);
949
+ Data_Get_Struct(self, xmlNode, xnode);
950
+ Data_Get_Struct(next, xmlNode, xnext);
938
951
 
939
- ret = xmlAddNextSibling(pnode, cnode);
940
- if (ret == NULL)
952
+ xresult = xmlAddNextSibling(xnode, xnext);
953
+ if (xresult == NULL)
941
954
  rxml_raise(&xmlLastError);
942
955
 
943
- return (rxml_node_wrap(ret));
956
+ return rxml_node_wrap(xresult);
944
957
  }
945
958
 
946
959
  /*
@@ -1037,21 +1050,21 @@ static VALUE rxml_node_prev_get(VALUE self)
1037
1050
  *
1038
1051
  * Insert the specified node as this node's previous sibling.
1039
1052
  */
1040
- static VALUE rxml_node_prev_set(VALUE self, VALUE rnode)
1053
+ static VALUE rxml_node_prev_set(VALUE self, VALUE prev)
1041
1054
  {
1042
- xmlNodePtr cnode, pnode, ret;
1055
+ xmlNodePtr xnode, xprev, xresult;
1043
1056
 
1044
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1057
+ if (rb_obj_is_kind_of(prev, cXMLNode) == Qfalse)
1045
1058
  rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1046
1059
 
1047
- Data_Get_Struct(self, xmlNode, pnode);
1048
- Data_Get_Struct(rnode, xmlNode, cnode);
1060
+ Data_Get_Struct(self, xmlNode, xnode);
1061
+ Data_Get_Struct(prev, xmlNode, xprev);
1049
1062
 
1050
- ret = xmlAddPrevSibling(pnode, cnode);
1051
- if (ret == NULL)
1063
+ xresult = xmlAddPrevSibling(xnode, xprev);
1064
+ if (xresult == NULL)
1052
1065
  rxml_raise(&xmlLastError);
1053
1066
 
1054
- return (rxml_node_wrap(ret));
1067
+ return rxml_node_wrap(xresult);
1055
1068
  }
1056
1069
 
1057
1070
  /*
@@ -1108,8 +1121,10 @@ static VALUE rxml_node_remove_ex(VALUE self)
1108
1121
  {
1109
1122
  xmlNodePtr xnode;
1110
1123
  Data_Get_Struct(self, xmlNode, xnode);
1124
+
1111
1125
  /* Unlink the node from its parent. */
1112
1126
  xmlUnlinkNode(xnode);
1127
+
1113
1128
  /* Now set the nodes parent to nil so it can
1114
1129
  be freed if the reference to it goes out of scope*/
1115
1130
  xmlSetTreeDoc(xnode, NULL);
@@ -1125,27 +1140,111 @@ static VALUE rxml_node_remove_ex(VALUE self)
1125
1140
  *
1126
1141
  * Add the specified node as a sibling of this node.
1127
1142
  */
1128
- static VALUE rxml_node_sibling_set(VALUE self, VALUE rnode)
1143
+ static VALUE rxml_node_sibling_set(VALUE self, VALUE sibling)
1129
1144
  {
1130
- xmlNodePtr cnode, pnode, ret;
1131
- VALUE obj;
1145
+ xmlNodePtr xnode, xsibling, xresult;
1132
1146
 
1133
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1147
+ if (rb_obj_is_kind_of(sibling, cXMLNode) == Qfalse)
1134
1148
  rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1135
1149
 
1136
- Data_Get_Struct(self, xmlNode, pnode);
1137
- Data_Get_Struct(rnode, xmlNode, cnode);
1150
+ Data_Get_Struct(self, xmlNode, xnode);
1151
+ Data_Get_Struct(sibling, xmlNode, xsibling);
1138
1152
 
1139
- ret = xmlAddSibling(pnode, cnode);
1140
- if (ret == NULL)
1153
+ xresult = xmlAddSibling(xnode, xsibling);
1154
+ if (xresult == NULL)
1141
1155
  rxml_raise(&xmlLastError);
1142
1156
 
1143
- if (ret->_private == NULL)
1144
- obj = rxml_node_wrap(ret);
1145
- else
1146
- obj = (VALUE) ret->_private;
1157
+ return rxml_node_wrap(xresult);
1158
+ }
1147
1159
 
1148
- return obj;
1160
+ /*
1161
+ * call-seq:
1162
+ * text_node.output_escaping? -> (true|false)
1163
+ * element_node.output_escaping? -> (true|false|nil)
1164
+ * attribute_node.output_escaping? -> (true|false|nil)
1165
+ * other_node.output_escaping? -> (nil)
1166
+ *
1167
+ * Determine whether this node escapes it's output or not.
1168
+ *
1169
+ * Text nodes return only +true+ or +false+. Element and attribute nodes
1170
+ * examine their immediate text node children to determine the value.
1171
+ * Any other type of node always returns +nil+.
1172
+ *
1173
+ * If an element or attribute node has at least one immediate child text node
1174
+ * and all the immediate text node children have the same +output_escaping?+
1175
+ * value, that value is returned. Otherwise, +nil+ is returned.
1176
+ */
1177
+ static VALUE rxml_node_output_escaping_q(VALUE self)
1178
+ {
1179
+ xmlNodePtr xnode;
1180
+ Data_Get_Struct(self, xmlNode, xnode);
1181
+
1182
+ switch (xnode->type) {
1183
+ case XML_TEXT_NODE:
1184
+ return xnode->name==xmlStringTextNoenc ? Qfalse : Qtrue;
1185
+ case XML_ELEMENT_NODE:
1186
+ case XML_ATTRIBUTE_NODE:
1187
+ {
1188
+ xmlNodePtr tmp = xnode->children;
1189
+ const xmlChar *match = NULL;
1190
+
1191
+ /* Find the first text node and use it as the reference. */
1192
+ while (tmp && tmp->type != XML_TEXT_NODE)
1193
+ tmp = tmp->next;
1194
+ if (! tmp)
1195
+ return Qnil;
1196
+ match = tmp->name;
1197
+
1198
+ /* Walk the remaining text nodes until we run out or one doesn't match. */
1199
+ while (tmp && (tmp->type != XML_TEXT_NODE || match == tmp->name))
1200
+ tmp = tmp->next;
1201
+
1202
+ /* We're left with either the mismatched node or the aggregate result. */
1203
+ return tmp ? Qnil : (match==xmlStringTextNoenc ? Qfalse : Qtrue);
1204
+ }
1205
+ break;
1206
+ default:
1207
+ return Qnil;
1208
+ }
1209
+ }
1210
+
1211
+ /*
1212
+ * call-seq:
1213
+ * text_node.output_escaping = true|false
1214
+ * element_node.output_escaping = true|false
1215
+ * attribute_node.output_escaping = true|false
1216
+ *
1217
+ * Controls whether this text node or the immediate text node children of an
1218
+ * element or attribute node escapes their output. Any other type of node
1219
+ * will simply ignore this operation.
1220
+ *
1221
+ * Text nodes which are added to an element or attribute node will be affected
1222
+ * by any previous setting of this property.
1223
+ */
1224
+ static VALUE rxml_node_output_escaping_set(VALUE self, VALUE bool)
1225
+ {
1226
+ xmlNodePtr xnode;
1227
+ Data_Get_Struct(self, xmlNode, xnode);
1228
+
1229
+ switch (xnode->type) {
1230
+ case XML_TEXT_NODE:
1231
+ xnode->name = (bool!=Qfalse && bool!=Qnil) ? xmlStringText : xmlStringTextNoenc;
1232
+ break;
1233
+ case XML_ELEMENT_NODE:
1234
+ case XML_ATTRIBUTE_NODE:
1235
+ {
1236
+ const xmlChar *name = (bool!=Qfalse && bool!=Qnil) ? xmlStringText : xmlStringTextNoenc;
1237
+ xmlNodePtr tmp;
1238
+ for (tmp = xnode->children; tmp; tmp = tmp->next)
1239
+ if (tmp->type == XML_TEXT_NODE)
1240
+ tmp->name = name;
1241
+ }
1242
+ break;
1243
+ default:
1244
+ return Qnil;
1245
+ }
1246
+
1247
+ return (bool!=Qfalse && bool!=Qnil) ? Qtrue : Qfalse;
1149
1248
  }
1150
1249
 
1151
1250
  /*
@@ -1219,47 +1318,10 @@ static VALUE rxml_node_copy(VALUE self, VALUE deep)
1219
1318
  return Qnil;
1220
1319
  }
1221
1320
 
1222
- void rxml_node_registerNode(xmlNodePtr node)
1223
- {
1224
- node->_private = NULL;
1225
- }
1226
-
1227
- void rxml_node_deregisterNode(xmlNodePtr xnode)
1228
- {
1229
- VALUE node;
1230
-
1231
- if (xnode->_private == NULL)
1232
- return;
1233
- node = (VALUE) xnode->_private;
1234
- DATA_PTR( node) = NULL;
1235
- }
1236
-
1237
- // Rdoc needs to know
1238
- #ifdef RDOC_NEVER_DEFINED
1239
- mLibXML = rb_define_module("LibXML");
1240
- mXML = rb_define_module_under(mLibXML, "XML");
1241
- #endif
1242
-
1243
- static VALUE rxml_constant_stringref(const xmlChar *ptr)
1244
- {
1245
- VALUE str = rb_str_new("", 0);
1246
- FL_SET(str, ELTS_SHARED | FL_USER3);
1247
- xfree(RSTRING_PTR(str));
1248
- RSTRING_PTR(str) = (void*)ptr;
1249
- RSTRING_LEN(str) = strlen(ptr);
1250
- RSTRING(str)->aux.capa = 0;
1251
- OBJ_FREEZE(str);
1252
- return str;
1253
- }
1254
-
1255
- void ruby_init_xml_node(void)
1321
+ void rxml_init_node(void)
1256
1322
  {
1257
- xmlRegisterNodeDefault(rxml_node_registerNode);
1258
1323
  xmlDeregisterNodeDefault(rxml_node_deregisterNode);
1259
1324
 
1260
- kXMLStringText = rxml_constant_stringref(xmlStringText);
1261
- kXMLStringTextNoenc = rxml_constant_stringref(xmlStringTextNoenc);
1262
-
1263
1325
  cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
1264
1326
 
1265
1327
  rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
@@ -1304,9 +1366,6 @@ void ruby_init_xml_node(void)
1304
1366
  rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", Qnil);
1305
1367
  #endif
1306
1368
 
1307
- rb_define_const(cXMLNode, "XML_STRING_TEXT", kXMLStringText);
1308
- rb_define_const(cXMLNode, "XML_STRING_TEXT_NOENC", kXMLStringTextNoenc);
1309
-
1310
1369
  rb_define_singleton_method(cXMLNode, "new_cdata", rxml_node_new_cdata, -1);
1311
1370
  rb_define_singleton_method(cXMLNode, "new_comment", rxml_node_new_comment, -1);
1312
1371
  rb_define_singleton_method(cXMLNode, "new_text", rxml_node_new_text, 1);
@@ -1353,6 +1412,8 @@ void ruby_init_xml_node(void)
1353
1412
  rb_define_method(cXMLNode, "name", rxml_node_name_get, 0);
1354
1413
  rb_define_method(cXMLNode, "name=", rxml_node_name_set, 1);
1355
1414
  rb_define_method(cXMLNode, "node_type", rxml_node_type, 0);
1415
+ rb_define_method(cXMLNode, "output_escaping?", rxml_node_output_escaping_q, 0);
1416
+ rb_define_method(cXMLNode, "output_escaping=", rxml_node_output_escaping_set, 1);
1356
1417
  rb_define_method(cXMLNode, "path", rxml_node_path, 0);
1357
1418
  rb_define_method(cXMLNode, "pointer", rxml_node_pointer, 1);
1358
1419
  rb_define_method(cXMLNode, "remove!", rxml_node_remove_ex, 0);