libxml-ruby 0.9.8 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +41 -1
- data/LICENSE +3 -4
- data/README +37 -24
- data/Rakefile +2 -2
- data/ext/libxml/extconf.rb +31 -12
- data/ext/libxml/libxml.c +56 -858
- data/ext/libxml/ruby_libxml.h +93 -96
- data/ext/libxml/ruby_xml.c +855 -0
- data/ext/libxml/ruby_xml.h +9 -0
- data/ext/libxml/ruby_xml_attr.c +3 -9
- data/ext/libxml/ruby_xml_attr.h +2 -2
- data/ext/libxml/ruby_xml_attr_decl.c +2 -8
- data/ext/libxml/ruby_xml_attr_decl.h +1 -1
- data/ext/libxml/ruby_xml_attributes.c +6 -8
- data/ext/libxml/ruby_xml_attributes.h +1 -1
- data/ext/libxml/ruby_xml_document.c +915 -895
- data/ext/libxml/ruby_xml_document.h +2 -2
- data/ext/libxml/ruby_xml_dtd.c +257 -136
- data/ext/libxml/ruby_xml_dtd.h +1 -1
- data/ext/libxml/ruby_xml_encoding.c +55 -37
- data/ext/libxml/ruby_xml_encoding.h +1 -1
- data/ext/libxml/ruby_xml_error.c +526 -1058
- data/ext/libxml/ruby_xml_error.h +1 -1
- data/ext/libxml/ruby_xml_html_parser.c +2 -8
- data/ext/libxml/ruby_xml_html_parser.h +2 -2
- data/ext/libxml/ruby_xml_html_parser_context.c +175 -145
- data/ext/libxml/ruby_xml_html_parser_context.h +1 -1
- data/ext/libxml/ruby_xml_html_parser_options.c +12 -20
- data/ext/libxml/ruby_xml_html_parser_options.h +1 -1
- data/ext/libxml/ruby_xml_input_cbg.c +2 -8
- data/ext/libxml/ruby_xml_input_cbg.h +1 -1
- data/ext/libxml/ruby_xml_namespace.c +2 -8
- data/ext/libxml/ruby_xml_namespace.h +2 -2
- data/ext/libxml/ruby_xml_namespaces.c +1 -9
- data/ext/libxml/ruby_xml_namespaces.h +1 -1
- data/ext/libxml/ruby_xml_node.c +182 -121
- data/ext/libxml/ruby_xml_node.h +2 -2
- data/ext/libxml/ruby_xml_parser.c +2 -8
- data/ext/libxml/ruby_xml_parser.h +2 -2
- data/ext/libxml/ruby_xml_parser_context.c +952 -901
- data/ext/libxml/ruby_xml_parser_context.h +2 -2
- data/ext/libxml/ruby_xml_parser_options.c +2 -9
- data/ext/libxml/ruby_xml_parser_options.h +1 -1
- data/ext/libxml/ruby_xml_reader.c +1002 -993
- data/ext/libxml/ruby_xml_reader.h +1 -1
- data/ext/libxml/ruby_xml_relaxng.c +1 -7
- data/ext/libxml/ruby_xml_relaxng.h +1 -1
- data/ext/libxml/ruby_xml_sax2_handler.c +2 -2
- data/ext/libxml/ruby_xml_sax2_handler.h +1 -1
- data/ext/libxml/ruby_xml_sax_parser.c +2 -8
- data/ext/libxml/ruby_xml_sax_parser.h +2 -2
- data/ext/libxml/ruby_xml_schema.c +1 -7
- data/ext/libxml/ruby_xml_schema.h +1 -1
- data/ext/libxml/{version.h → ruby_xml_version.h} +2 -2
- data/ext/libxml/ruby_xml_xinclude.c +2 -8
- data/ext/libxml/ruby_xml_xinclude.h +2 -2
- data/ext/libxml/ruby_xml_xpath.c +17 -18
- data/ext/libxml/ruby_xml_xpath.h +2 -2
- data/ext/libxml/ruby_xml_xpath_context.c +387 -389
- data/ext/libxml/ruby_xml_xpath_context.h +2 -2
- data/ext/libxml/ruby_xml_xpath_expression.c +18 -8
- data/ext/libxml/ruby_xml_xpath_expression.h +1 -1
- data/ext/libxml/ruby_xml_xpath_object.c +19 -8
- data/ext/libxml/ruby_xml_xpath_object.h +1 -1
- data/ext/libxml/ruby_xml_xpointer.c +2 -8
- data/ext/libxml/ruby_xml_xpointer.h +2 -2
- data/ext/vc/libxml_ruby.sln +7 -1
- data/lib/libxml.rb +1 -12
- data/lib/libxml/attr.rb +0 -3
- data/lib/libxml/attr_decl.rb +0 -3
- data/lib/libxml/attributes.rb +0 -3
- data/lib/libxml/document.rb +31 -5
- data/lib/libxml/error.rb +8 -4
- data/lib/libxml/properties.rb +0 -5
- data/lib/libxml/sax_callbacks.rb +30 -19
- data/lib/libxml/tree.rb +0 -1
- data/lib/libxml/xpath_object.rb +0 -13
- data/test/model/definition.dtd +8 -0
- data/test/tc_attributes.rb +4 -1
- data/test/tc_document.rb +16 -0
- data/test/tc_dtd.rb +30 -2
- data/test/tc_html_parser.rb +55 -10
- data/test/tc_node.rb +67 -1
- data/test/tc_node_edit.rb +26 -6
- data/test/tc_node_text.rb +41 -23
- data/test/tc_parser.rb +50 -0
- data/test/tc_reader.rb +15 -0
- data/test/tc_relaxng.rb +1 -1
- data/test/tc_sax_parser.rb +37 -5
- data/test/tc_schema.rb +1 -1
- data/test/tc_xpath.rb +1 -0
- data/test/tc_xpath_expression.rb +4 -2
- metadata +6 -6
- data/ext/libxml/ruby_xml_state.c +0 -51
- data/ext/libxml/ruby_xml_state.h +0 -11
- data/ext/vc/libxml_ruby.vcproj +0 -460
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: ruby_xml_namespace.c
|
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
|
-
|
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
|
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
|
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);
|
data/ext/libxml/ruby_xml_node.c
CHANGED
@@ -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
|
-
*
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
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
|
-
*
|
39
|
-
*
|
40
|
-
*
|
41
|
-
*
|
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
|
-
/*
|
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
|
410
|
+
static VALUE rxml_node_child_set_aux(VALUE self, VALUE child)
|
385
411
|
{
|
386
|
-
xmlNodePtr
|
412
|
+
xmlNodePtr xnode, xchild, xresult;
|
387
413
|
|
388
|
-
if (rb_obj_is_kind_of(
|
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,
|
392
|
-
Data_Get_Struct(
|
417
|
+
Data_Get_Struct(self, xmlNode, xnode);
|
418
|
+
Data_Get_Struct(child, xmlNode, xchild);
|
393
419
|
|
394
|
-
if (
|
395
|
-
rb_raise(
|
396
|
-
|
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
|
-
|
400
|
-
|
401
|
-
|
424
|
+
xresult = xmlAddChild(xnode, xchild);
|
425
|
+
|
426
|
+
if (!xresult)
|
402
427
|
rxml_raise(&xmlLastError);
|
403
|
-
|
404
|
-
|
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
|
624
|
+
xmlNodePtr xcurrent;
|
607
625
|
Data_Get_Struct(self, xmlNode, xnode);
|
608
626
|
|
609
|
-
|
627
|
+
xcurrent = xnode->children;
|
610
628
|
|
611
|
-
while (
|
629
|
+
while (xcurrent)
|
612
630
|
{
|
613
|
-
|
614
|
-
|
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
|
942
|
+
static VALUE rxml_node_next_set(VALUE self, VALUE next)
|
930
943
|
{
|
931
|
-
xmlNodePtr
|
944
|
+
xmlNodePtr xnode, xnext, xresult;
|
932
945
|
|
933
|
-
if (rb_obj_is_kind_of(
|
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,
|
937
|
-
Data_Get_Struct(
|
949
|
+
Data_Get_Struct(self, xmlNode, xnode);
|
950
|
+
Data_Get_Struct(next, xmlNode, xnext);
|
938
951
|
|
939
|
-
|
940
|
-
if (
|
952
|
+
xresult = xmlAddNextSibling(xnode, xnext);
|
953
|
+
if (xresult == NULL)
|
941
954
|
rxml_raise(&xmlLastError);
|
942
955
|
|
943
|
-
return
|
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
|
1053
|
+
static VALUE rxml_node_prev_set(VALUE self, VALUE prev)
|
1041
1054
|
{
|
1042
|
-
xmlNodePtr
|
1055
|
+
xmlNodePtr xnode, xprev, xresult;
|
1043
1056
|
|
1044
|
-
if (rb_obj_is_kind_of(
|
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,
|
1048
|
-
Data_Get_Struct(
|
1060
|
+
Data_Get_Struct(self, xmlNode, xnode);
|
1061
|
+
Data_Get_Struct(prev, xmlNode, xprev);
|
1049
1062
|
|
1050
|
-
|
1051
|
-
if (
|
1063
|
+
xresult = xmlAddPrevSibling(xnode, xprev);
|
1064
|
+
if (xresult == NULL)
|
1052
1065
|
rxml_raise(&xmlLastError);
|
1053
1066
|
|
1054
|
-
return
|
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
|
1143
|
+
static VALUE rxml_node_sibling_set(VALUE self, VALUE sibling)
|
1129
1144
|
{
|
1130
|
-
xmlNodePtr
|
1131
|
-
VALUE obj;
|
1145
|
+
xmlNodePtr xnode, xsibling, xresult;
|
1132
1146
|
|
1133
|
-
if (rb_obj_is_kind_of(
|
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,
|
1137
|
-
Data_Get_Struct(
|
1150
|
+
Data_Get_Struct(self, xmlNode, xnode);
|
1151
|
+
Data_Get_Struct(sibling, xmlNode, xsibling);
|
1138
1152
|
|
1139
|
-
|
1140
|
-
if (
|
1153
|
+
xresult = xmlAddSibling(xnode, xsibling);
|
1154
|
+
if (xresult == NULL)
|
1141
1155
|
rxml_raise(&xmlLastError);
|
1142
1156
|
|
1143
|
-
|
1144
|
-
|
1145
|
-
else
|
1146
|
-
obj = (VALUE) ret->_private;
|
1157
|
+
return rxml_node_wrap(xresult);
|
1158
|
+
}
|
1147
1159
|
|
1148
|
-
|
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
|
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);
|