libxml-ruby 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/CHANGES +18 -0
  2. data/RAKEFILE +15 -39
  3. data/README +48 -47
  4. data/ext/libxml/libxml.c +847 -22
  5. data/ext/libxml/ruby_libxml.h +71 -95
  6. data/ext/libxml/ruby_xml_attr.c +500 -500
  7. data/ext/libxml/ruby_xml_attributes.c +1 -1
  8. data/ext/libxml/ruby_xml_document.c +1144 -1135
  9. data/ext/libxml/ruby_xml_document.h +4 -11
  10. data/ext/libxml/ruby_xml_dtd.c +27 -0
  11. data/ext/libxml/ruby_xml_encoding.c +164 -0
  12. data/ext/libxml/ruby_xml_encoding.h +13 -0
  13. data/ext/libxml/ruby_xml_error.c +941 -0
  14. data/ext/libxml/ruby_xml_error.h +13 -0
  15. data/ext/libxml/ruby_xml_html_parser.c +71 -387
  16. data/ext/libxml/ruby_xml_html_parser.h +1 -17
  17. data/ext/libxml/ruby_xml_input.c +179 -0
  18. data/ext/libxml/ruby_xml_input.h +18 -0
  19. data/ext/libxml/ruby_xml_input_cbg.c +17 -3
  20. data/ext/libxml/ruby_xml_node.c +1566 -1582
  21. data/ext/libxml/ruby_xml_node.h +1 -4
  22. data/ext/libxml/ruby_xml_ns.c +14 -3
  23. data/ext/libxml/ruby_xml_parser.c +164 -1398
  24. data/ext/libxml/ruby_xml_parser.h +5 -17
  25. data/ext/libxml/ruby_xml_parser_context.c +131 -169
  26. data/ext/libxml/ruby_xml_parser_context.h +2 -9
  27. data/ext/libxml/ruby_xml_reader.c +910 -945
  28. data/ext/libxml/ruby_xml_relaxng.c +32 -3
  29. data/ext/libxml/ruby_xml_sax_parser.c +106 -364
  30. data/ext/libxml/ruby_xml_sax_parser.h +1 -37
  31. data/ext/libxml/ruby_xml_schema.c +174 -145
  32. data/ext/libxml/ruby_xml_xinclude.c +9 -5
  33. data/ext/libxml/ruby_xml_xpath.c +25 -6
  34. data/ext/libxml/ruby_xml_xpath.h +1 -2
  35. data/ext/libxml/ruby_xml_xpath_context.c +17 -19
  36. data/ext/libxml/ruby_xml_xpath_object.c +60 -56
  37. data/ext/libxml/ruby_xml_xpointer.c +11 -5
  38. data/ext/libxml/sax_parser_callbacks.inc +42 -37
  39. data/ext/libxml/version.h +3 -3
  40. data/ext/mingw/Rakefile +20 -27
  41. data/ext/mingw/build.rake +41 -0
  42. data/ext/vc/libxml_ruby.vcproj +23 -15
  43. data/lib/libxml.rb +8 -2
  44. data/lib/libxml/document.rb +16 -4
  45. data/lib/libxml/error.rb +84 -0
  46. data/lib/libxml/hpricot.rb +76 -0
  47. data/lib/libxml/html_parser.rb +61 -0
  48. data/lib/libxml/node.rb +36 -25
  49. data/lib/libxml/parser.rb +312 -33
  50. data/lib/libxml/parser_context.rb +17 -0
  51. data/lib/libxml/properties.rb +15 -2
  52. data/lib/libxml/reader.rb +15 -0
  53. data/lib/libxml/sax_callbacks.rb +179 -0
  54. data/lib/libxml/sax_parser.rb +42 -0
  55. data/lib/libxml/tree.rb +1 -2
  56. data/lib/libxml/xpath_object.rb +12 -0
  57. data/test/model/atom.xml +4 -0
  58. data/test/tc_attributes.rb +43 -19
  59. data/test/tc_document.rb +1 -1
  60. data/test/tc_document_write.rb +15 -8
  61. data/test/tc_dtd.rb +36 -20
  62. data/test/tc_encoding.rb +13 -0
  63. data/test/tc_error.rb +136 -0
  64. data/test/tc_node.rb +2 -3
  65. data/test/tc_node_copy.rb +1 -1
  66. data/test/tc_node_edit.rb +6 -0
  67. data/test/tc_ns.rb +18 -0
  68. data/test/tc_parser.rb +113 -228
  69. data/test/tc_parser_context.rb +1 -2
  70. data/test/tc_reader.rb +24 -14
  71. data/test/tc_relaxng.rb +18 -6
  72. data/test/tc_sax_parser.rb +48 -13
  73. data/test/tc_schema.rb +20 -8
  74. data/test/tc_well_formed.rb +2 -1
  75. data/test/tc_xml.rb +212 -0
  76. data/test/tc_xpath.rb +60 -46
  77. data/test/tc_xpointer.rb +7 -11
  78. data/test/test_suite.rb +4 -3
  79. metadata +26 -109
  80. data/doc/rdoc/classes/LibXML.html +0 -241
  81. data/doc/rdoc/classes/LibXML/XML.html +0 -185
  82. data/doc/rdoc/classes/LibXML/XML/Attr.html +0 -1010
  83. data/doc/rdoc/classes/LibXML/XML/Attributes.html +0 -526
  84. data/doc/rdoc/classes/LibXML/XML/Document.html +0 -1489
  85. data/doc/rdoc/classes/LibXML/XML/Dtd.html +0 -213
  86. data/doc/rdoc/classes/LibXML/XML/Error.html +0 -117
  87. data/doc/rdoc/classes/LibXML/XML/HTMLParser.html +0 -348
  88. data/doc/rdoc/classes/LibXML/XML/InputCallbacks.html +0 -160
  89. data/doc/rdoc/classes/LibXML/XML/NS.html +0 -381
  90. data/doc/rdoc/classes/LibXML/XML/Node.html +0 -3396
  91. data/doc/rdoc/classes/LibXML/XML/Node/FailedModify.html +0 -123
  92. data/doc/rdoc/classes/LibXML/XML/Node/Set.html +0 -440
  93. data/doc/rdoc/classes/LibXML/XML/Node/SetNamespace.html +0 -123
  94. data/doc/rdoc/classes/LibXML/XML/Node/UnknownType.html +0 -123
  95. data/doc/rdoc/classes/LibXML/XML/Parser.html +0 -2239
  96. data/doc/rdoc/classes/LibXML/XML/Parser/Context.html +0 -1255
  97. data/doc/rdoc/classes/LibXML/XML/Parser/ParseError.html +0 -123
  98. data/doc/rdoc/classes/LibXML/XML/Reader.html +0 -2264
  99. data/doc/rdoc/classes/LibXML/XML/RelaxNG.html +0 -237
  100. data/doc/rdoc/classes/LibXML/XML/SaxParser.html +0 -415
  101. data/doc/rdoc/classes/LibXML/XML/Schema.html +0 -308
  102. data/doc/rdoc/classes/LibXML/XML/State.html +0 -124
  103. data/doc/rdoc/classes/LibXML/XML/Tree.html +0 -111
  104. data/doc/rdoc/classes/LibXML/XML/XInclude.html +0 -123
  105. data/doc/rdoc/classes/LibXML/XML/XInclude/Error.html +0 -117
  106. data/doc/rdoc/classes/LibXML/XML/XMLParserOptions.html +0 -198
  107. data/doc/rdoc/classes/LibXML/XML/XPath.html +0 -184
  108. data/doc/rdoc/classes/LibXML/XML/XPath/Context.html +0 -404
  109. data/doc/rdoc/classes/LibXML/XML/XPath/InvalidPath.html +0 -172
  110. data/doc/rdoc/classes/LibXML/XML/XPath/Object.html +0 -627
  111. data/doc/rdoc/classes/LibXML/XML/XPointer.html +0 -170
  112. data/doc/rdoc/classes/LibXML/XML/XPointer/Context.html +0 -123
  113. data/doc/rdoc/classes/LibXML/XML/XPointer/Context/InvalidPath.html +0 -117
  114. data/doc/rdoc/classes/LibXML/XML/XPointer/InvalidExpression.html +0 -124
  115. data/doc/rdoc/classes/singleton.html +0 -114
  116. data/doc/rdoc/created.rid +0 -1
  117. data/doc/rdoc/files/CHANGES.html +0 -442
  118. data/doc/rdoc/files/LICENSE.html +0 -133
  119. data/doc/rdoc/files/README.html +0 -388
  120. data/doc/rdoc/files/VERSION.html +0 -107
  121. data/doc/rdoc/files/ext/libxml/cbg_c.html +0 -101
  122. data/doc/rdoc/files/ext/libxml/libxml_c.html +0 -101
  123. data/doc/rdoc/files/ext/libxml/ruby_xml_attr_c.html +0 -101
  124. data/doc/rdoc/files/ext/libxml/ruby_xml_attributes_c.html +0 -101
  125. data/doc/rdoc/files/ext/libxml/ruby_xml_document_c.html +0 -101
  126. data/doc/rdoc/files/ext/libxml/ruby_xml_dtd_c.html +0 -101
  127. data/doc/rdoc/files/ext/libxml/ruby_xml_html_parser_c.html +0 -101
  128. data/doc/rdoc/files/ext/libxml/ruby_xml_input_cbg_c.html +0 -101
  129. data/doc/rdoc/files/ext/libxml/ruby_xml_node_c.html +0 -101
  130. data/doc/rdoc/files/ext/libxml/ruby_xml_node_set_c.html +0 -101
  131. data/doc/rdoc/files/ext/libxml/ruby_xml_ns_c.html +0 -101
  132. data/doc/rdoc/files/ext/libxml/ruby_xml_parser_c.html +0 -101
  133. data/doc/rdoc/files/ext/libxml/ruby_xml_parser_context_c.html +0 -101
  134. data/doc/rdoc/files/ext/libxml/ruby_xml_reader_c.html +0 -101
  135. data/doc/rdoc/files/ext/libxml/ruby_xml_relaxng_c.html +0 -101
  136. data/doc/rdoc/files/ext/libxml/ruby_xml_sax_parser_c.html +0 -101
  137. data/doc/rdoc/files/ext/libxml/ruby_xml_schema_c.html +0 -101
  138. data/doc/rdoc/files/ext/libxml/ruby_xml_state_c.html +0 -101
  139. data/doc/rdoc/files/ext/libxml/ruby_xml_xinclude_c.html +0 -101
  140. data/doc/rdoc/files/ext/libxml/ruby_xml_xpath_c.html +0 -101
  141. data/doc/rdoc/files/ext/libxml/ruby_xml_xpath_context_c.html +0 -101
  142. data/doc/rdoc/files/ext/libxml/ruby_xml_xpath_object_c.html +0 -101
  143. data/doc/rdoc/files/ext/libxml/ruby_xml_xpointer_c.html +0 -101
  144. data/doc/rdoc/files/ext/libxml/ruby_xml_xpointer_context_c.html +0 -101
  145. data/doc/rdoc/files/lib/libxml/attr_rb.html +0 -108
  146. data/doc/rdoc/files/lib/libxml/attributes_rb.html +0 -108
  147. data/doc/rdoc/files/lib/libxml/document_rb.html +0 -108
  148. data/doc/rdoc/files/lib/libxml/node_rb.html +0 -108
  149. data/doc/rdoc/files/lib/libxml/node_set_rb.html +0 -108
  150. data/doc/rdoc/files/lib/libxml/parser_options_rb.html +0 -107
  151. data/doc/rdoc/files/lib/libxml/parser_rb.html +0 -101
  152. data/doc/rdoc/files/lib/libxml/properties_rb.html +0 -108
  153. data/doc/rdoc/files/lib/libxml/tree_rb.html +0 -107
  154. data/doc/rdoc/files/lib/libxml_rb.html +0 -124
  155. data/doc/rdoc/files/lib/xml/libxml_rb.html +0 -124
  156. data/doc/rdoc/files/lib/xml_rb.html +0 -134
  157. data/doc/rdoc/fr_class_index.html +0 -62
  158. data/doc/rdoc/fr_file_index.html +0 -66
  159. data/doc/rdoc/fr_method_index.html +0 -392
  160. data/doc/rdoc/index.html +0 -24
  161. data/doc/rdoc/rdoc-style.css +0 -208
  162. data/ext/libxml/ruby_xml_node_set.c +0 -172
  163. data/ext/libxml/ruby_xml_node_set.h +0 -20
  164. data/ext/libxml/ruby_xml_xpointer_context.c +0 -22
  165. data/ext/libxml/ruby_xml_xpointer_context.h +0 -18
  166. data/lib/libxml/node_set.rb +0 -27
  167. data/test/tc_node_set.rb +0 -24
  168. data/test/tc_node_set2.rb +0 -37
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_html_parser.h 111 2006-11-20 01:39:14Z roscopeco $ */
1
+ /* $Id: ruby_xml_html_parser.h 545 2008-11-17 05:29:39Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -8,22 +8,6 @@
8
8
  extern int ruby_xml_html_parser_count;
9
9
  extern VALUE cXMLHTMLParser;
10
10
 
11
- typedef struct ruby_xml_html_parser {
12
- VALUE ctxt;
13
- int parsed;
14
- void *data;
15
- int data_type;
16
- } ruby_xml_html_parser;
17
-
18
- /*
19
- * VALUE ruby_xml_html_parser_filename_get(VALUE self);
20
- VALUE ruby_xml_html_parser_filename_set(VALUE self, VALUE filename);
21
- VALUE ruby_xml_html_parser_new(VALUE class);
22
- */
23
- VALUE ruby_xml_html_parser_parse(VALUE self);
24
- VALUE ruby_xml_html_parser_str_get(VALUE self);
25
- VALUE ruby_xml_html_parser_str_set(VALUE self, VALUE str);
26
-
27
11
  void ruby_init_html_parser(void);
28
12
 
29
13
  #endif
@@ -0,0 +1,179 @@
1
+ /* $Id: ruby_xml_input.c 528 2008-11-15 23:43:48Z cfis $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include <stdarg.h>
6
+ #include "ruby_libxml.h"
7
+
8
+ VALUE cXMLInput;
9
+
10
+ /*
11
+ * Document-class: LibXML::XML::Input
12
+ *
13
+ * Input is a helper class that defines a libxml data source.
14
+ * Libxml can parse files, strings, io streams and documents
15
+ * accessible via networking protocols such as http.
16
+ * Be default, the ruby-libxml bindings expose parsing
17
+ * files, io streams and strings.
18
+ *
19
+ * Generally you will not directly work with the input object,
20
+ * but instead will use the various Document and Parser apis.
21
+ * For example:
22
+ *
23
+ * document = Document.file('my_file') */
24
+
25
+ ID ENCODING_ATTR;
26
+ ID FILE_ATTR;
27
+ ID STRING_ATTR;
28
+ ID DOCUMENT_ATTR;
29
+ ID IO_ATTR;
30
+
31
+ /*
32
+ * call-seq:
33
+ * initialize -> LibXML::XML::Input instance
34
+ *
35
+ * Initialize a new intput object.
36
+ */
37
+ VALUE
38
+ ruby_xml_input_initialize(VALUE self) {
39
+ rb_ivar_set(self, ENCODING_ATTR, INT2NUM(XML_CHAR_ENCODING_UTF8));
40
+ return self;
41
+ }
42
+
43
+
44
+ /*
45
+ * call-seq:
46
+ * input.FILE -> "FILE"
47
+ *
48
+ * Obtain the FILE this parser will read from.
49
+ */
50
+ VALUE
51
+ ruby_xml_input_file_get(VALUE self) {
52
+ return rb_ivar_get(self, FILE_ATTR);
53
+ }
54
+
55
+ /*
56
+ * call-seq:
57
+ * input.FILE = "FILE"
58
+ *
59
+ * Set the FILE this parser will read from.
60
+ */
61
+ VALUE
62
+ ruby_xml_input_file_set(VALUE self, VALUE FILE) {
63
+ Check_Type(FILE, T_STRING);
64
+ rb_ivar_set(self, FILE_ATTR, FILE);
65
+ rb_ivar_set(self, STRING_ATTR, Qnil);
66
+ rb_ivar_set(self, DOCUMENT_ATTR, Qnil);
67
+ rb_ivar_set(self, IO_ATTR, Qnil);
68
+ return self;
69
+ }
70
+
71
+
72
+ /*
73
+ * call-seq:
74
+ * input.string -> "string"
75
+ *
76
+ * Obtain the string this parser will read from.
77
+ */
78
+ VALUE
79
+ ruby_xml_input_string_get(VALUE self) {
80
+ return rb_ivar_get(self, STRING_ATTR);
81
+ }
82
+
83
+
84
+ /*
85
+ * call-seq:
86
+ * input.string = "string"
87
+ *
88
+ * Set the string this parser will read from.
89
+ */
90
+ VALUE
91
+ ruby_xml_input_string_set(VALUE self, VALUE string) {
92
+ Check_Type(string, T_STRING);
93
+ rb_ivar_set(self, FILE_ATTR, Qnil);
94
+ rb_ivar_set(self, STRING_ATTR, string);
95
+ rb_ivar_set(self, DOCUMENT_ATTR, Qnil);
96
+ rb_ivar_set(self, IO_ATTR, Qnil);
97
+ return self;
98
+ }
99
+
100
+ /*
101
+ * call-seq:
102
+ * input.document -> "document"
103
+ *
104
+ * Obtain the document this parser will read from.
105
+ */
106
+ VALUE
107
+ ruby_xml_input_document_get(VALUE self) {
108
+ return rb_ivar_get(self, DOCUMENT_ATTR);
109
+ }
110
+
111
+ /*
112
+ * call-seq:
113
+ * input.document = LibXML::XML::Document.new
114
+ *
115
+ * Set the document this parser will read from.
116
+ */
117
+ VALUE
118
+ ruby_xml_input_document_set(VALUE self, VALUE document) {
119
+ rb_ivar_set(self, FILE_ATTR, Qnil);
120
+ rb_ivar_set(self, STRING_ATTR, Qnil);
121
+ rb_ivar_set(self, DOCUMENT_ATTR, document);
122
+ rb_ivar_set(self, IO_ATTR, Qnil);
123
+ return self;
124
+ }
125
+
126
+ /*
127
+ * call-seq:
128
+ * input.io -> IO
129
+ *
130
+ * Obtain the IO instance this parser works with.
131
+ */
132
+ VALUE
133
+ ruby_xml_input_io_get(VALUE self) {
134
+ return rb_ivar_get(self, IO_ATTR);
135
+ }
136
+
137
+ /*
138
+ * call-seq:
139
+ * input.io = IO
140
+ *
141
+ * Set the IO instance this parser works with.
142
+ */
143
+ VALUE
144
+ ruby_xml_input_io_set(VALUE self, VALUE io) {
145
+ if (!rb_obj_is_kind_of(io, rb_cIO))
146
+ rb_raise(rb_eTypeError, "Invalid argument, must be an IO object");
147
+
148
+ rb_ivar_set(self, FILE_ATTR, Qnil);
149
+ rb_ivar_set(self, STRING_ATTR, Qnil);
150
+ rb_ivar_set(self, DOCUMENT_ATTR, Qnil);
151
+ rb_ivar_set(self, IO_ATTR, io);
152
+ return self;
153
+ }
154
+
155
+ // Rdoc needs to know
156
+ #ifdef RDOC_NEVER_DEFINED
157
+ mLibXML = rb_define_module("LibXML");
158
+ mXML = rb_define_module_under(mLibXML, "XML");
159
+ #endif
160
+
161
+ void
162
+ ruby_init_xml_input(void) {
163
+ FILE_ATTR = rb_intern("@FILE");
164
+ STRING_ATTR = rb_intern("@string");
165
+ DOCUMENT_ATTR = rb_intern("@document");
166
+ IO_ATTR = rb_intern("@io");
167
+
168
+ cXMLInput = rb_define_class_under(mXML, "Input", rb_cObject);
169
+ rb_define_attr(cXMLInput, "encoding", 1, 1);
170
+ rb_define_method(cXMLInput, "initialize", ruby_xml_input_initialize, 0);
171
+ rb_define_method(cXMLInput, "file", ruby_xml_input_file_get, 0);
172
+ rb_define_method(cXMLInput, "file=", ruby_xml_input_file_set, 1);
173
+ rb_define_method(cXMLInput, "string", ruby_xml_input_string_get, 0);
174
+ rb_define_method(cXMLInput, "string=", ruby_xml_input_string_set, 1);
175
+ rb_define_method(cXMLInput, "document", ruby_xml_input_document_get, 0);
176
+ rb_define_method(cXMLInput, "document=", ruby_xml_input_document_set, 1);
177
+ rb_define_method(cXMLInput, "io", ruby_xml_input_io_get, 0);
178
+ rb_define_method(cXMLInput, "io=", ruby_xml_input_io_set, 1);
179
+ }
@@ -0,0 +1,18 @@
1
+ /* $Id: ruby_xml_parser.h 39 2006-02-21 20:40:16Z roscopeco $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __RUBY_XML_INPUT__
6
+ #define __RUBY_XML_INPUT__
7
+
8
+ extern VALUE cXMLInput;
9
+
10
+ void ruby_init_xml_input();
11
+
12
+ extern ID ENCODING_ATTR;
13
+ extern ID FILE_ATTR;
14
+ extern ID STRING_ATTR;
15
+ extern ID DOCUMENT_ATTR;
16
+ extern ID IO_ATTR;
17
+
18
+ #endif
@@ -1,10 +1,12 @@
1
-
2
- /* ruby support for custom scheme handlers */
3
1
  /* Author: Martin Povolny (xpovolny@fi.muni.cz) */
4
2
 
5
3
  #include "ruby_libxml.h"
6
4
  #include "ruby_xml_input_cbg.h"
7
5
 
6
+ /* Document-class: LibXML::XML::InputCallbacks
7
+ *
8
+ * Support for adding custom scheme handlers. */
9
+
8
10
  static ic_scheme *first_scheme = 0;
9
11
 
10
12
  int ic_match (char const *filename) {
@@ -82,6 +84,13 @@ VALUE input_callbacks_register_input_callbacks() {
82
84
  return(Qtrue);
83
85
  }
84
86
 
87
+
88
+ /*
89
+ * call-seq:
90
+ * add_scheme
91
+ *
92
+ * No documentation available.
93
+ */
85
94
  VALUE
86
95
  input_callbacks_add_scheme (VALUE self, VALUE scheme_name, VALUE class) {
87
96
  ic_scheme *scheme;
@@ -109,6 +118,12 @@ input_callbacks_add_scheme (VALUE self, VALUE scheme_name, VALUE class) {
109
118
  return(Qtrue);
110
119
  }
111
120
 
121
+ /*
122
+ * call-seq:
123
+ * remove_scheme
124
+ *
125
+ * No documentation available.
126
+ */
112
127
  VALUE
113
128
  input_callbacks_remove_scheme (VALUE self, VALUE scheme_name) {
114
129
  char *name;
@@ -120,7 +135,6 @@ input_callbacks_remove_scheme (VALUE self, VALUE scheme_name) {
120
135
  if (0 == first_scheme)
121
136
  return Qfalse;
122
137
 
123
- /* check the first one */
124
138
  if (!strncmp(name, first_scheme->scheme_name, first_scheme->name_len)) {
125
139
  save_scheme = first_scheme->next_scheme;
126
140
 
@@ -1,1582 +1,1566 @@
1
- /* $Id: ruby_xml_node.c 497 2008-07-22 01:33:51Z cfis $ */
2
-
3
- /* Please see the LICENSE file for copyright and distribution information */
4
-
5
- #include "ruby_libxml.h"
6
- #include "ruby_xml_node.h"
7
-
8
- VALUE cXMLNode;
9
- VALUE eXMLNodeSetNamespace;
10
- VALUE eXMLNodeFailedModify;
11
- VALUE eXMLNodeUnknownType;
12
-
13
- 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
-
22
-
23
- /*
24
- * call-seq:
25
- * node.base -> "uri"
26
- *
27
- * Obtain this node's base URI.
28
- */
29
- VALUE
30
- ruby_xml_node_base_get(VALUE self) {
31
- xmlNodePtr xnode;
32
- xmlChar* base_uri;
33
- VALUE result = Qnil;
34
-
35
- Data_Get_Struct(self, xmlNode, xnode);
36
-
37
- if (xnode->doc == NULL)
38
- return(result);
39
-
40
- base_uri = xmlNodeGetBase(xnode->doc, xnode);
41
- if (base_uri) {
42
- result = rb_str_new2((const char*)base_uri);
43
- xmlFree(base_uri);
44
- }
45
-
46
- return(result);
47
- }
48
-
49
-
50
- // TODO node_base_set should support setting back to nil
51
-
52
- /*
53
- * call-seq:
54
- * node.base = "uri"
55
- *
56
- * Set this node's base URI.
57
- */
58
- VALUE
59
- ruby_xml_node_base_set(VALUE self, VALUE uri) {
60
- xmlNodePtr xnode;
61
-
62
- Check_Type(uri, T_STRING);
63
- Data_Get_Struct(self, xmlNode, xnode);
64
- if (xnode->doc == NULL)
65
- return(Qnil);
66
-
67
- xmlNodeSetBase(xnode, (xmlChar*)StringValuePtr(uri));
68
- return(Qtrue);
69
- }
70
-
71
-
72
- /*
73
- * call-seq:
74
- * node.content -> "string"
75
- *
76
- * Obtain this node's content as a string.
77
- */
78
- VALUE
79
- ruby_xml_node_content_get(VALUE self) {
80
- xmlNodePtr xnode;
81
- xmlChar *content;
82
- VALUE result = Qnil;
83
-
84
- Data_Get_Struct(self, xmlNode, xnode);
85
- content = xmlNodeGetContent(xnode);
86
- if (content) {
87
- result = rb_str_new2((const char *) content);
88
- xmlFree(content);
89
- }
90
-
91
- return result;
92
- }
93
-
94
- /*
95
- * call-seq:
96
- * node.content = "string"
97
- *
98
- * Set this node's content to the specified string.
99
- */
100
- VALUE
101
- ruby_xml_node_content_set(VALUE self, VALUE content) {
102
- xmlNodePtr xnode;
103
-
104
- Check_Type(content, T_STRING);
105
- Data_Get_Struct(self, xmlNode, xnode);
106
- // XXX docs indicate need for escaping entites, need to be done? danj
107
- xmlNodeSetContent(xnode, (xmlChar*)StringValuePtr(content));
108
- return(Qtrue);
109
- }
110
-
111
-
112
- /*
113
- * call-seq:
114
- * node.content_stripped -> "string"
115
- *
116
- * Obtain this node's stripped content.
117
- *
118
- * *Deprecated*: Stripped content can be obtained via the
119
- * +content+ method.
120
- */
121
- VALUE
122
- ruby_xml_node_content_stripped_get(VALUE self) {
123
- xmlNodePtr xnode;
124
- xmlChar* content;
125
- VALUE result = Qnil;
126
-
127
- Data_Get_Struct(self, xmlNode, xnode);
128
-
129
- if (!xnode->content)
130
- return result;
131
-
132
- content = xmlNodeGetContent(xnode);
133
- if (content) {
134
- result = rb_str_new2((const char*)content);
135
- xmlFree(content);
136
- }
137
- return(result);
138
- }
139
-
140
- /*
141
- * call-seq:
142
- * node.first -> XML::Node
143
- *
144
- * Returns this node's first child node if any.
145
- */
146
- VALUE
147
- ruby_xml_node_first_get(VALUE self) {
148
- xmlNodePtr xnode;
149
-
150
- Data_Get_Struct(self, xmlNode, xnode);
151
-
152
- if (xnode->children)
153
- return(ruby_xml_node2_wrap(cXMLNode, xnode->children));
154
- else
155
- return(Qnil);
156
- }
157
-
158
-
159
- /*
160
- * underlying for child_set and child_add, difference being
161
- * former raises on implicit copy, latter does not.
162
- */
163
- VALUE
164
- ruby_xml_node_child_set_aux(VALUE self, VALUE rnode) {
165
- xmlNodePtr pnode, chld, ret;
166
-
167
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
168
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
169
-
170
- Data_Get_Struct(self, xmlNode, pnode);
171
- Data_Get_Struct(rnode, xmlNode, chld);
172
-
173
- if ( chld->parent != NULL || chld->doc != NULL )
174
- rb_raise(rb_eRuntimeError, "Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
175
-
176
- ret = xmlAddChild(pnode, chld);
177
- if (ret == NULL) {
178
- rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
179
- } else if ( ret==chld ) {
180
- /* child was added whole to parent and we need to return it as a new object */
181
- return ruby_xml_node2_wrap(cXMLNode,chld);
182
- }
183
- /* else */
184
- /* If it was a text node, then ret should be parent->last, so we will just return ret. */
185
- return ruby_xml_node2_wrap(cXMLNode,ret);
186
- }
187
-
188
- /*
189
- * call-seq:
190
- * node.child = node
191
- *
192
- * Set a child node for this node. Also called for <<
193
- */
194
- VALUE
195
- ruby_xml_node_child_set(VALUE self, VALUE rnode) {
196
- return ruby_xml_node_child_set_aux(self, rnode);
197
- }
198
-
199
-
200
- /*
201
- * call-seq:
202
- * node << ("string" | node) -> XML::Node
203
- *
204
- * Add the specified string or XML::Node to this node's
205
- * content.
206
- */
207
- VALUE
208
- ruby_xml_node_content_add(VALUE self, VALUE obj) {
209
- xmlNodePtr xnode;
210
- VALUE str;
211
-
212
- Data_Get_Struct(self, xmlNode, xnode);
213
- /* XXX This should only be legal for a CDATA type node, I think,
214
- * resulting in a merge of content, as if a string were passed
215
- * danj 070827
216
- */
217
- if (rb_obj_is_kind_of(obj, cXMLNode)) {
218
- ruby_xml_node_child_set(self, obj);
219
- return(self);
220
- } else if (TYPE(obj) == T_STRING) {
221
- xmlNodeAddContent(xnode, (xmlChar*)StringValuePtr(obj));
222
- return(self);
223
- } else {
224
- str = rb_obj_as_string(obj);
225
- if (NIL_P(str) || TYPE(str) != T_STRING)
226
- rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
227
-
228
- xmlNodeAddContent(xnode, (xmlChar*)StringValuePtr(str));
229
- return(self);
230
- }
231
- }
232
-
233
- /*
234
- * call-seq:
235
- * node.child_add(node)
236
- *
237
- * Set a child node for this node.
238
- */
239
- VALUE
240
- ruby_xml_node_child_add(VALUE self, VALUE rnode) {
241
- return ruby_xml_node_child_set_aux(self, rnode);
242
- }
243
-
244
- /*
245
- * call-seq:
246
- * node.doc -> document
247
- *
248
- * Obtain the XML::Document this node belongs to.
249
- */
250
- VALUE
251
- ruby_xml_node_doc(VALUE self) {
252
- xmlNodePtr xnode;
253
- xmlDocPtr doc=NULL;
254
-
255
- Data_Get_Struct(self, xmlNode, xnode);
256
-
257
- switch (xnode->type) {
258
- case XML_DOCUMENT_NODE:
259
- #ifdef LIBXML_DOCB_ENABLED
260
- case XML_DOCB_DOCUMENT_NODE:
261
- #endif
262
- case XML_HTML_DOCUMENT_NODE:
263
- doc = NULL;
264
- break;
265
- case XML_ATTRIBUTE_NODE:
266
- {
267
- xmlAttrPtr attr = (xmlAttrPtr) xnode;
268
- doc = attr->doc;
269
- break;
270
- }
271
- case XML_NAMESPACE_DECL:
272
- doc = NULL;
273
- break;
274
- default:
275
- doc = xnode->doc;
276
- break;
277
- }
278
-
279
- if (doc == NULL)
280
- return(Qnil);
281
-
282
- if ( doc->_private == NULL )
283
- rb_raise(rb_eRuntimeError,"existing document object has no ruby-instance");
284
-
285
- return (VALUE)doc->_private;
286
- }
287
-
288
-
289
- /*
290
- * call-seq:
291
- * node.dump -> (true|nil)
292
- *
293
- * Dump this node to stdout.
294
- */
295
- VALUE
296
- ruby_xml_node_dump(VALUE self) {
297
- xmlNodePtr xnode;
298
- xmlBufferPtr buf;
299
-
300
- Data_Get_Struct(self, xmlNode, xnode);
301
-
302
- if (xnode->doc == NULL)
303
- return(Qnil);
304
-
305
- buf = xmlBufferCreate();
306
- xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
307
- xmlBufferDump(stdout, buf);
308
- xmlBufferFree(buf);
309
- return(Qtrue);
310
- }
311
-
312
-
313
- /*
314
- * call-seq:
315
- * node.debug_dump -> (true|nil)
316
- *
317
- * Dump this node to stdout, including any debugging
318
- * information.
319
- */
320
- VALUE
321
- ruby_xml_node_debug_dump(VALUE self) {
322
- xmlNodePtr xnode;
323
- Data_Get_Struct(self, xmlNode, xnode);
324
-
325
- if (xnode->doc == NULL)
326
- return(Qnil);
327
-
328
- xmlElemDump(stdout, xnode->doc, xnode);
329
- return(Qtrue);
330
- }
331
-
332
- /*
333
- * call-seq:
334
- * node.each -> XML::Node
335
- *
336
- * Iterates over this node's children, including text
337
- * nodes, element nodes, etc. If you wish to iterate
338
- * only over child elements, use XML::Node#each_element.
339
- *
340
- * doc = XML::Document.new('model/books.xml')
341
- * doc.root.each {|node| puts node}
342
- */
343
- VALUE
344
- ruby_xml_node_each(VALUE self) {
345
- xmlNodePtr xnode;
346
- xmlNodePtr xchild;
347
- Data_Get_Struct(self, xmlNode, xnode);
348
-
349
- xchild = xnode->children;
350
-
351
- while (xchild) {
352
- rb_yield(ruby_xml_node2_wrap(cXMLNode, xchild));
353
- xchild = xchild->next;
354
- }
355
- return Qnil;
356
- }
357
-
358
-
359
- /*
360
- * call-seq:
361
- * node.empty? -> (true|false)
362
- *
363
- * Determine whether this node is empty.
364
- */
365
- VALUE
366
- ruby_xml_node_empty_q(VALUE self) {
367
- xmlNodePtr xnode;
368
- Data_Get_Struct(self, xmlNode, xnode);
369
- if (xnode == NULL)
370
- return(Qnil);
371
-
372
- return((xmlIsBlankNode(xnode) == 1) ? Qtrue : Qfalse);
373
- }
374
-
375
-
376
- VALUE ruby_xml_node_to_s(VALUE self);
377
-
378
- /*
379
- * call-seq:
380
- * node.eql?(other_node) => (true|false)
381
- *
382
- * Test equality between the two nodes. Two nodes are equal
383
- * if they are the same node or have the same XML representation.*/
384
- VALUE
385
- ruby_xml_node_eql_q(VALUE self, VALUE other) {
386
- if (self == other)
387
- {
388
- return Qtrue;
389
- }
390
- else if NIL_P(other)
391
- {
392
- return Qfalse;
393
- }
394
- else
395
- {
396
- VALUE self_xml;
397
- VALUE other_xml;
398
-
399
- if (rb_obj_is_kind_of(other, cXMLNode) == Qfalse)
400
- rb_raise(rb_eTypeError, "Nodes can only be compared against other nodes");
401
-
402
- self_xml = ruby_xml_node_to_s(self);
403
- other_xml = ruby_xml_node_to_s(other);
404
- return(rb_funcall(self_xml, rb_intern("=="), 1, other_xml));
405
- }
406
- }
407
-
408
- /*
409
- * call-seq:
410
- * XML::Node.new_cdata(content = nil) -> XML::Node
411
- *
412
- * Create a new #CDATA node, optionally setting
413
- * the node's content.
414
- */
415
- VALUE
416
- ruby_xml_node_new_cdata(int argc, VALUE *argv, VALUE class) {
417
- xmlNodePtr xnode;
418
- VALUE str=Qnil;
419
-
420
- switch(argc) {
421
- case 1:
422
- str = argv[0];
423
- Check_Type(str, T_STRING);
424
- if (!NIL_P(str)) {
425
- xnode = xmlNewCDataBlock(NULL, (xmlChar*)StringValuePtr(str), xmlStrlen((xmlChar*)StringValuePtr(str)));
426
- } else {
427
- xnode = xmlNewCDataBlock(NULL, NULL , 0);
428
- }
429
-
430
- if (xnode == NULL)
431
- return(Qnil);
432
-
433
- return ruby_xml_node2_wrap(class,xnode);
434
-
435
- default:
436
- rb_raise(rb_eArgError, "wrong number of arguments (1)");
437
- }
438
-
439
- // not reached
440
- return(Qnil);
441
- }
442
-
443
-
444
- /*
445
- * call-seq:
446
- * XML::Node.new_comment(content = nil) -> XML::Node
447
- *
448
- * Create a new comment node, optionally setting
449
- * the node's content.
450
- *
451
- */
452
- VALUE
453
- ruby_xml_node_new_comment(int argc, VALUE *argv, VALUE class) {
454
- xmlNodePtr xnode;
455
- VALUE str=Qnil;
456
-
457
- switch(argc) {
458
- case 1:
459
- str = argv[0];
460
- Check_Type(str, T_STRING);
461
- // TODO xmlNewComment wrongly? adds \n before and after the comment
462
- if (!NIL_P(str)) {
463
- xnode = xmlNewComment((xmlChar*)StringValuePtr(str));
464
- } else {
465
- xnode = xmlNewComment(NULL);
466
- }
467
-
468
- if (xnode == NULL)
469
- return(Qnil);
470
-
471
- return ruby_xml_node2_wrap(class,xnode);
472
-
473
- default:
474
- rb_raise(rb_eArgError, "wrong number of arguments (1)");
475
- }
476
-
477
- // not reached
478
- return(Qnil);
479
- }
480
-
481
-
482
- /*
483
- * call-seq:
484
- * node.lang -> "string"
485
- *
486
- * Obtain the language set for this node, if any.
487
- * This is set in XML via the xml:lang attribute.
488
- */
489
- VALUE
490
- ruby_xml_node_lang_get(VALUE self) {
491
- xmlNodePtr xnode;
492
- xmlChar *lang;
493
- VALUE result = Qnil;
494
-
495
- Data_Get_Struct(self, xmlNode, xnode);
496
- lang = xmlNodeGetLang(xnode);
497
-
498
- if (lang) {
499
- result = rb_str_new2((const char*)lang);
500
- xmlFree(lang);
501
- }
502
-
503
- return(result);
504
- }
505
-
506
-
507
- // TODO node_lang_set should support setting back to nil
508
-
509
- /*
510
- * call-seq:
511
- * node.lang = "string"
512
- *
513
- * Set the language for this node. This affects the value
514
- * of the xml:lang attribute.
515
- */
516
- VALUE
517
- ruby_xml_node_lang_set(VALUE self, VALUE lang) {
518
- xmlNodePtr xnode;
519
-
520
- Check_Type(lang, T_STRING);
521
- Data_Get_Struct(self, xmlNode, xnode);
522
- xmlNodeSetLang(xnode, (xmlChar*)StringValuePtr(lang));
523
-
524
- return(Qtrue);
525
- }
526
-
527
-
528
- /*
529
- * call-seq:
530
- * node.last -> XML::Node
531
- *
532
- * Obtain the last child node of this node, if any.
533
- */
534
- VALUE
535
- ruby_xml_node_last_get(VALUE self) {
536
- xmlNodePtr xnode;
537
-
538
- Data_Get_Struct(self, xmlNode, xnode);
539
-
540
- if (xnode->last)
541
- return(ruby_xml_node2_wrap(cXMLNode, xnode->last));
542
- else
543
- return(Qnil);
544
- }
545
-
546
- /*
547
- * call-seq:
548
- * node.line_num -> num
549
- *
550
- * Obtain the line number (in the XML document) that this
551
- * node was read from. If +default_line_numbers+ is set
552
- * false (the default), this method returns zero.
553
- */
554
- VALUE
555
- ruby_xml_node_line_num(VALUE self) {
556
- xmlNodePtr xnode;
557
- long line_num;
558
- Data_Get_Struct(self, xmlNode, xnode);
559
-
560
- if (!xmlLineNumbersDefaultValue)
561
- rb_warn("Line numbers were not retained: use XML::Parser::default_line_numbers=true");
562
-
563
- line_num = xmlGetLineNo(xnode);
564
- if (line_num == -1)
565
- return(Qnil);
566
- else
567
- return(INT2NUM((long)line_num));
568
- }
569
-
570
-
571
- /*
572
- * call-seq:
573
- * node.xlink? -> (true|false)
574
- *
575
- * Determine whether this node is an xlink node.
576
- */
577
- VALUE
578
- ruby_xml_node_xlink_q(VALUE self) {
579
- xmlNodePtr xnode;
580
- xlinkType xlt;
581
-
582
- Data_Get_Struct(self, xmlNode, xnode);
583
- xlt = xlinkIsLink(xnode->doc, xnode);
584
-
585
- if (xlt == XLINK_TYPE_NONE)
586
- return(Qfalse);
587
- else
588
- return(Qtrue);
589
- }
590
-
591
-
592
- /*
593
- * call-seq:
594
- * node.xlink_type -> num
595
- *
596
- * Obtain the type identifier for this xlink, if applicable.
597
- * If this is not an xlink node (see +xlink?+), will return
598
- * nil.
599
- */
600
- VALUE
601
- ruby_xml_node_xlink_type(VALUE self) {
602
- xmlNodePtr xnode;
603
- xlinkType xlt;
604
-
605
- Data_Get_Struct(self, xmlNode, xnode);
606
- xlt = xlinkIsLink(xnode->doc, xnode);
607
-
608
- if (xlt == XLINK_TYPE_NONE)
609
- return(Qnil);
610
- else
611
- return(INT2NUM(xlt));
612
- }
613
-
614
-
615
- /*
616
- * call-seq:
617
- * node.xlink_type_name -> "string"
618
- *
619
- * Obtain the type name for this xlink, if applicable.
620
- * If this is not an xlink node (see +xlink?+), will return
621
- * nil.
622
- */
623
- VALUE
624
- ruby_xml_node_xlink_type_name(VALUE self) {
625
- xmlNodePtr xnode;
626
- xlinkType xlt;
627
-
628
- Data_Get_Struct(self, xmlNode, xnode);
629
- xlt = xlinkIsLink(xnode->doc, xnode);
630
-
631
- switch(xlt) {
632
- case XLINK_TYPE_NONE:
633
- return(Qnil);
634
- case XLINK_TYPE_SIMPLE:
635
- return(rb_str_new2("simple"));
636
- case XLINK_TYPE_EXTENDED:
637
- return(rb_str_new2("extended"));
638
- case XLINK_TYPE_EXTENDED_SET:
639
- return(rb_str_new2("extended_set"));
640
- default:
641
- rb_fatal("Unknowng xlink type, %d", xlt);
642
- }
643
- }
644
-
645
- /*
646
- * call-seq:
647
- * node.name -> "string"
648
- *
649
- * Obtain this node's name.
650
- */
651
- VALUE
652
- ruby_xml_node_name_get(VALUE self) {
653
- xmlNodePtr xnode;
654
- const xmlChar *name;
655
-
656
- Data_Get_Struct(self, xmlNode, xnode);
657
-
658
- switch (xnode->type) {
659
- case XML_DOCUMENT_NODE:
660
- #ifdef LIBXML_DOCB_ENABLED
661
- case XML_DOCB_DOCUMENT_NODE:
662
- #endif
663
- case XML_HTML_DOCUMENT_NODE:
664
- {
665
- xmlDocPtr doc = (xmlDocPtr) xnode;
666
- name = doc->URL;
667
- break;
668
- }
669
- case XML_ATTRIBUTE_NODE:
670
- {
671
- xmlAttrPtr attr = (xmlAttrPtr) xnode;
672
- name = attr->name;
673
- break;
674
- }
675
- case XML_NAMESPACE_DECL:
676
- {
677
- xmlNsPtr ns = (xmlNsPtr) xnode;
678
- name = ns->prefix;
679
- break;
680
- }
681
- default:
682
- name = xnode->name;
683
- break;
684
- }
685
-
686
- if (xnode->name == NULL)
687
- return(Qnil);
688
- else
689
- return(rb_str_new2((const char*)name));
690
- }
691
-
692
-
693
- /*
694
- * call-seq:
695
- * node.name = "string"
696
- *
697
- * Set this node's name.
698
- */
699
- VALUE
700
- ruby_xml_node_name_set(VALUE self, VALUE name) {
701
- xmlNodePtr xnode;
702
-
703
- Check_Type(name, T_STRING);
704
- Data_Get_Struct(self, xmlNode, xnode);
705
- xmlNodeSetName(xnode, (xmlChar*)StringValuePtr(name));
706
- return(Qtrue);
707
- }
708
-
709
-
710
- /*
711
- * call-seq:
712
- * node.namespace -> [namespace, ..., namespace]
713
- *
714
- * Obtain an array of +XML::NS+ objects representing
715
- * this node's xmlns attributes
716
- */
717
- VALUE
718
- ruby_xml_node_namespace_get(VALUE self) {
719
- xmlNodePtr xnode;
720
- xmlNsPtr *nsList, *cur;
721
- VALUE arr, ns;
722
-
723
- Data_Get_Struct(self, xmlNode, xnode);
724
- if (xnode == NULL)
725
- return(Qnil);
726
-
727
- nsList = xmlGetNsList(xnode->doc, xnode);
728
-
729
- if (nsList == NULL)
730
- return(Qnil);
731
-
732
- arr = rb_ary_new();
733
- for (cur = nsList; *cur != NULL; cur++) {
734
- ns = ruby_xml_ns_wrap(*cur);
735
- if (ns == Qnil)
736
- continue;
737
- else
738
- rb_ary_push(arr, ns);
739
- }
740
- xmlFree(nsList);
741
-
742
- return(arr);
743
- }
744
-
745
-
746
- /*
747
- * call-seq:
748
- * node.namespace_node -> namespace.
749
- *
750
- * Obtain this node's namespace node.
751
- */
752
- VALUE
753
- ruby_xml_node_namespace_get_node(VALUE self) {
754
- xmlNodePtr xnode;
755
-
756
- Data_Get_Struct(self, xmlNode, xnode);
757
- if (xnode->ns == NULL)
758
- return(Qnil);
759
- else
760
- return ruby_xml_ns_wrap(xnode->ns);
761
- }
762
-
763
- // TODO namespace_set can take varargs (in fact, must if used
764
- // with strings), but I cannot see how you can call
765
- // that version, apart from with 'send'
766
- //
767
- // Would sure be nice to support foo.namespace['foo'] = 'bar'
768
- // but maybe that's not practical...
769
-
770
- /*
771
- * call-seq:
772
- * node.namespace = namespace
773
- *
774
- * Add the specified XML::NS object to this node's xmlns attributes.
775
- */
776
- VALUE
777
- ruby_xml_node_namespace_set(int argc, VALUE *argv, VALUE self) {
778
- VALUE rns, rprefix;
779
- xmlNodePtr xnode;
780
- xmlNsPtr xns;
781
- char *cp, *href;
782
-
783
- Data_Get_Struct(self, xmlNode, xnode);
784
- switch (argc) {
785
- case 1:
786
- rns = argv[0];
787
- if (TYPE(rns) == T_STRING) {
788
- cp = strchr(StringValuePtr(rns), (int)':');
789
- if (cp == NULL) {
790
- rprefix = rns;
791
- href = NULL;
792
- } else {
793
- rprefix = rb_str_new(StringValuePtr(rns), (int)((long)cp - (long)StringValuePtr(rns)));
794
- href = &cp[1]; /* skip the : */
795
- }
796
- } else if (rb_obj_is_kind_of(rns, cXMLNS) == Qtrue) {
797
- Data_Get_Struct(self, xmlNs, xns);
798
- xmlSetNs(xnode, xns);
799
- return(rns);
800
- } else
801
- rb_raise(rb_eTypeError, "must pass a string or an XML::Ns object");
802
-
803
- /* Fall through to next case because when argc == 1, we need to
804
- * manually setup the additional args unless the arg passed is of
805
- * cXMLNS type */
806
- case 2:
807
- /* Don't want this code run in the fall through case */
808
- if (argc == 2) {
809
- rprefix = argv[0];
810
- href = StringValuePtr(argv[1]);
811
- }
812
-
813
- xns = xmlNewNs(xnode, (xmlChar*)href, (xmlChar*)StringValuePtr(rprefix));
814
- if (xns == NULL)
815
- rb_raise(eXMLNodeSetNamespace, "unable to set the namespace");
816
- else
817
- return ruby_xml_ns_wrap(xns);
818
- break;
819
-
820
- default:
821
- rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
822
- }
823
-
824
- /* can't get here */
825
- return(Qnil);
826
- }
827
-
828
-
829
- /*
830
- * memory2 implementation: xmlNode->_private holds a reference
831
- * to the wrapping ruby object VALUE when there is one.
832
- * traversal for marking is upward, and top levels are marked
833
- * through and lower level mark entry.
834
- *
835
- * All ruby retrieval for an xml
836
- * node will result in the same ruby instance. When all handles to them
837
- * go out of scope, then ruby_xfree gets called and _private is set to NULL.
838
- * If the xmlNode has no parent or document, then call xmlFree.
839
- */
840
- void
841
- ruby_xml_node2_free(xmlNodePtr xnode) {
842
-
843
- if (xnode != NULL) {
844
- xnode->_private=NULL;
845
-
846
- if (xnode->doc==NULL && xnode->parent==NULL) {
847
- #ifdef NODE_DEBUG
848
- fprintf(stderr,"ruby_xml_node2_free ruby_xfree rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)xnode,(long)xnode->_private);
849
- #endif
850
- xmlFreeNode(xnode);
851
- }
852
- }
853
- }
854
-
855
- void
856
- ruby_xml_node_mark_common(xmlNodePtr xnode) {
857
- if (xnode->parent == NULL ) {
858
- #ifdef NODE_DEBUG
859
- fprintf(stderr,"mark no parent r=0x%x *n=0x%x\n",rxn,node);
860
- #endif
861
- } else if (xnode->doc != NULL ) {
862
- if (xnode->doc->_private == NULL) {
863
- rb_bug("XmlNode Doc is not bound! (%s:%d)",
864
- __FILE__,__LINE__);
865
- }
866
- rb_gc_mark((VALUE)xnode->doc->_private);
867
- } else {
868
- while (xnode->parent != NULL )
869
- xnode = xnode->parent;
870
- if (xnode->_private == NULL )
871
- rb_warning("XmlNode Root Parent is not bound! (%s:%d)",
872
- __FILE__,__LINE__);
873
- else {
874
- #ifdef NODE_DEBUG
875
- fprintf(stderr,"mark rxn=0x%x xn=0x%x o=0x%x doc=0x%x\n",(long)rxn,(long)node,(long)node->_private,node->doc);
876
- #endif
877
- rb_gc_mark((VALUE)xnode->_private);
878
- }
879
- }
880
- }
881
-
882
- void
883
- ruby_xml_node2_mark(xmlNodePtr xnode) {
884
- if (xnode == NULL ) return;
885
-
886
- if (xnode->_private == NULL ) {
887
- rb_warning("XmlNode is not bound! (%s:%d)",
888
- __FILE__,__LINE__);
889
- return;
890
- }
891
-
892
- ruby_xml_node_mark_common(xnode);
893
- }
894
-
895
- VALUE
896
- ruby_xml_node2_wrap(VALUE class, xmlNodePtr xnode)
897
- {
898
- VALUE obj;
899
-
900
- // This node is already wrapped
901
- if (xnode->_private != NULL) {
902
- #ifdef NODE_DEBUG
903
- Data_Get_Struct((VALUE)xnode->_private,ruby_xml_node,rxn);
904
- fprintf(stderr,"re-wrap rn=0x%x n*=0x%x\n",(long)rxn,(long)xnode);
905
- #endif
906
- return (VALUE)xnode->_private;
907
- }
908
-
909
- obj=Data_Wrap_Struct(class,
910
- ruby_xml_node2_mark, ruby_xml_node2_free,
911
- xnode);
912
-
913
- xnode->_private=(void*)obj;
914
- #ifdef NODE_DEBUG
915
- fprintf(stderr,"wrap rn=0x%x n*=0x%x d*=0x%x\n",
916
- (long)rxn,(long)xnode,xnode->doc);
917
- #endif
918
- return obj;
919
- }
920
-
921
- VALUE
922
- ruby_xml_node2_new_native(VALUE class, VALUE ns, VALUE name)
923
- {
924
- VALUE obj;
925
- xmlNodePtr xnode;
926
- xmlNsPtr xns=NULL;
927
-
928
- if ( ! NIL_P(ns) ) {
929
- Data_Get_Struct(ns,xmlNs,xns);
930
- }
931
- xnode=xmlNewNode(xns,(xmlChar*)StringValuePtr(name));
932
- xnode->_private=NULL;
933
-
934
- obj= ruby_xml_node2_wrap(class,xnode);
935
-
936
- rb_obj_call_init(obj,0,NULL);
937
- return obj;
938
- }
939
-
940
- VALUE
941
- ruby_xml_node2_new_string(VALUE class, VALUE ns, VALUE name, VALUE val)
942
- {
943
- VALUE obj;
944
- obj=ruby_xml_node2_new_native(class,ns,name);
945
- if ( ! NIL_P(val) ) {
946
- if ( TYPE(val) != T_STRING )
947
- val=rb_obj_as_string(val);
948
- ruby_xml_node_content_set(obj,val);
949
- }
950
- return obj;
951
- }
952
- /*
953
- * call-seq:
954
- * XML::Node.new(name, content = nil) -> XML::Node
955
- * XML::Node.new_element(name, content = nil) -> XML::Node
956
- *
957
- * Create a new element node with the specified name, optionally setting
958
- * the node's content.
959
- * backward compatibility for <.5 new
960
- */
961
- VALUE
962
- ruby_xml_node2_new_string_bc(int argc, VALUE *argv, VALUE class)
963
- {
964
- VALUE content=Qnil;
965
- VALUE name=Qnil;
966
- switch(argc) {
967
- case 2:
968
- content=argv[1];
969
- if ( TYPE(content) != T_STRING)
970
- content=rb_obj_as_string(content);
971
-
972
- case 1:
973
- name=check_string_or_symbol( argv[0] );
974
- return ruby_xml_node2_new_string(class,Qnil,name,content);
975
-
976
- default:
977
- rb_raise(rb_eArgError, "wrong number of arguments (1 or 2) given %d",argc);
978
- }
979
- }
980
-
981
- /*
982
- * call-seq:
983
- * node.next -> XML::Node
984
- *
985
- * Obtain the next sibling node, if any.
986
- */
987
- VALUE
988
- ruby_xml_node_next_get(VALUE self) {
989
- xmlNodePtr xnode;
990
-
991
- Data_Get_Struct(self, xmlNode, xnode);
992
-
993
- if (xnode->next)
994
- return(ruby_xml_node2_wrap(cXMLNode, xnode->next));
995
- else
996
- return(Qnil);
997
- }
998
-
999
-
1000
- /*
1001
- * call-seq:
1002
- * node.next = node
1003
- *
1004
- * Insert the specified node as this node's next sibling.
1005
- */
1006
- VALUE
1007
- ruby_xml_node_next_set(VALUE self, VALUE rnode) {
1008
- xmlNodePtr cnode, pnode, ret;
1009
-
1010
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1011
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1012
-
1013
- Data_Get_Struct(self, xmlNode, pnode);
1014
- Data_Get_Struct(rnode, xmlNode, cnode);
1015
-
1016
- ret = xmlAddNextSibling(pnode, cnode);
1017
- if (ret == NULL)
1018
- rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
1019
-
1020
- return(ruby_xml_node2_wrap(cXMLNode, ret));
1021
- }
1022
-
1023
-
1024
- /*
1025
- * call-seq:
1026
- * node.ns? -> (true|false)
1027
- *
1028
- * Determine whether this node has a namespace.
1029
- */
1030
- VALUE
1031
- ruby_xml_node_ns_q(VALUE self) {
1032
- xmlNodePtr xnode;
1033
- Data_Get_Struct(self, xmlNode, xnode);
1034
- if (xnode->ns == NULL)
1035
- return(Qfalse);
1036
- else
1037
- return(Qtrue);
1038
- }
1039
-
1040
- /*
1041
- * call-seq:
1042
- * node.ns_def? -> (true|false)
1043
- *
1044
- * Obtain an array of +XML::NS+ objects representing
1045
- * this node's xmlns attributes
1046
- */
1047
- VALUE
1048
- ruby_xml_node_ns_def_q(VALUE self) {
1049
- xmlNodePtr xnode;
1050
- Data_Get_Struct(self, xmlNode, xnode);
1051
- if (xnode->nsDef == NULL)
1052
- return(Qfalse);
1053
- else
1054
- return(Qtrue);
1055
- }
1056
-
1057
-
1058
- /*
1059
- * call-seq:
1060
- * node.ns_def -> namespace
1061
- *
1062
- * Obtain this node's default namespace.
1063
- */
1064
- VALUE
1065
- ruby_xml_node_ns_def_get(VALUE self) {
1066
- xmlNodePtr xnode;
1067
- Data_Get_Struct(self, xmlNode, xnode);
1068
- if (xnode->nsDef == NULL)
1069
- return(Qnil);
1070
- else
1071
- return(ruby_xml_ns_wrap(xnode->nsDef));
1072
- }
1073
-
1074
-
1075
- /*
1076
- * call-seq:
1077
- * node.parent -> XML::Node
1078
- *
1079
- * Obtain this node's parent node, if any.
1080
- */
1081
- VALUE
1082
- ruby_xml_node_parent_get(VALUE self) {
1083
- xmlNodePtr xnode;
1084
-
1085
- Data_Get_Struct(self, xmlNode, xnode);
1086
-
1087
- if (xnode->parent)
1088
- return(ruby_xml_node2_wrap(cXMLNode, xnode->parent));
1089
- else
1090
- return(Qnil);
1091
- }
1092
-
1093
-
1094
- /*
1095
- * call-seq:
1096
- * node.path -> path
1097
- *
1098
- * Obtain this node's path.
1099
- */
1100
- VALUE
1101
- ruby_xml_node_path(VALUE self) {
1102
- xmlNodePtr xnode;
1103
- xmlChar *path;
1104
-
1105
- Data_Get_Struct(self, xmlNode, xnode);
1106
- path = xmlGetNodePath(xnode);
1107
-
1108
- if (path == NULL)
1109
- return(Qnil);
1110
- else
1111
- return(rb_str_new2((const char*)path));
1112
- }
1113
-
1114
-
1115
- /*
1116
- * call-seq:
1117
- * node.pointer -> XML::Node_set
1118
- *
1119
- * Evaluates an XPointer expression relative to this node.
1120
- */
1121
- VALUE
1122
- ruby_xml_node_pointer(VALUE self, VALUE xptr_str) {
1123
- return(ruby_xml_xpointer_point2(self, xptr_str));
1124
- }
1125
-
1126
-
1127
- /*
1128
- * call-seq:
1129
- * node.prev -> XML::Node
1130
- *
1131
- * Obtain the previous sibling, if any.
1132
- */
1133
- VALUE
1134
- ruby_xml_node_prev_get(VALUE self) {
1135
- xmlNodePtr xnode;
1136
- xmlNodePtr node;
1137
- Data_Get_Struct(self, xmlNode, xnode);
1138
-
1139
- switch (xnode->type) {
1140
- case XML_DOCUMENT_NODE:
1141
- #ifdef LIBXML_DOCB_ENABLED
1142
- case XML_DOCB_DOCUMENT_NODE:
1143
- #endif
1144
- case XML_HTML_DOCUMENT_NODE:
1145
- case XML_NAMESPACE_DECL:
1146
- node = NULL;
1147
- break;
1148
- case XML_ATTRIBUTE_NODE:
1149
- {
1150
- xmlAttrPtr attr = (xmlAttrPtr) xnode;
1151
- node = (xmlNodePtr) attr->prev;
1152
- }
1153
- break;
1154
- default:
1155
- node = xnode->prev;
1156
- break;
1157
- }
1158
-
1159
- if (node == NULL)
1160
- return(Qnil);
1161
- else
1162
- return(ruby_xml_node2_wrap(cXMLNode, node));
1163
- }
1164
-
1165
-
1166
- /*
1167
- * call-seq:
1168
- * node.prev = node
1169
- *
1170
- * Insert the specified node as this node's previous sibling.
1171
- */
1172
- VALUE
1173
- ruby_xml_node_prev_set(VALUE self, VALUE rnode) {
1174
- xmlNodePtr cnode, pnode, ret;
1175
-
1176
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1177
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1178
-
1179
- Data_Get_Struct(self, xmlNode, pnode);
1180
- Data_Get_Struct(rnode, xmlNode, cnode);
1181
-
1182
- ret = xmlAddPrevSibling(pnode, cnode);
1183
- if (ret == NULL)
1184
- rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
1185
-
1186
- return(ruby_xml_node2_wrap(cXMLNode, ret));
1187
- }
1188
-
1189
- /*
1190
- * call-seq:
1191
- * node.attributes -> attributes
1192
- *
1193
- * Returns the XML::Attributes for this node.
1194
- */
1195
- VALUE
1196
- ruby_xml_node_attributes_get(VALUE self) {
1197
- xmlNodePtr xnode;
1198
-
1199
- Data_Get_Struct(self, xmlNode, xnode);
1200
- return ruby_xml_attributes_new(xnode);
1201
- }
1202
-
1203
- /*
1204
- * call-seq:
1205
- * node.property("name") -> "string"
1206
- * node["name"] -> "string"
1207
- *
1208
- * Obtain the named property.
1209
- */
1210
- VALUE
1211
- ruby_xml_node_property_get(VALUE self, VALUE name) {
1212
- VALUE attributes = ruby_xml_node_attributes_get(self);
1213
- return ruby_xml_attributes_attribute_get(attributes, name);
1214
- }
1215
-
1216
- /*
1217
- * call-seq:
1218
- * node["name"] = "string"
1219
- *
1220
- * Set the named property.
1221
- */
1222
- VALUE
1223
- ruby_xml_node_property_set(VALUE self, VALUE name, VALUE value) {
1224
- VALUE attributes = ruby_xml_node_attributes_get(self);
1225
- return ruby_xml_attributes_attribute_set(attributes, name, value);
1226
- }
1227
-
1228
-
1229
- /*
1230
- * call-seq:
1231
- * node.remove! -> nil
1232
- *
1233
- * Removes this node from it's parent.
1234
- */
1235
- VALUE
1236
- ruby_xml_node_remove_ex(VALUE self) {
1237
- xmlNodePtr xnode;
1238
- Data_Get_Struct(self, xmlNode, xnode);
1239
- xmlUnlinkNode(xnode);
1240
- return(Qnil);
1241
- }
1242
-
1243
-
1244
- /*
1245
- * call-seq:
1246
- * node.search_href -> namespace
1247
- *
1248
- * Search for a namespace by href.
1249
- */
1250
- VALUE
1251
- ruby_xml_node_search_href(VALUE self, VALUE href) {
1252
- xmlNodePtr xnode;
1253
-
1254
- Check_Type(href, T_STRING);
1255
- Data_Get_Struct(self, xmlNode, xnode);
1256
- return(ruby_xml_ns_wrap(xmlSearchNsByHref(xnode->doc, xnode,
1257
- (xmlChar*)StringValuePtr(href))));
1258
- }
1259
-
1260
-
1261
- /*
1262
- * call-seq:
1263
- * node.search_ns -> namespace
1264
- *
1265
- * Search for a namespace by namespace.
1266
- */
1267
- VALUE
1268
- ruby_xml_node_search_ns(VALUE self, VALUE ns) {
1269
- xmlNodePtr xnode;
1270
-
1271
- Check_Type(ns, T_STRING);
1272
- Data_Get_Struct(self, xmlNode, xnode);
1273
- return(ruby_xml_ns_wrap(xmlSearchNs(xnode->doc, xnode,
1274
- (xmlChar*)StringValuePtr(ns))));
1275
- }
1276
-
1277
-
1278
- /*
1279
- * call-seq:
1280
- * node.sibling(node) -> XML::Node
1281
- *
1282
- * Add the specified node as a sibling of this node.
1283
- */
1284
- VALUE
1285
- ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
1286
- xmlNodePtr cnode, pnode, ret;
1287
- VALUE obj;
1288
-
1289
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1290
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1291
-
1292
- Data_Get_Struct(self, xmlNode, pnode);
1293
- Data_Get_Struct(rnode, xmlNode, cnode);
1294
-
1295
- ret = xmlAddSibling(pnode, cnode);
1296
- if (ret == NULL)
1297
- rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
1298
- if (ret->_private==NULL)
1299
- obj=ruby_xml_node2_wrap(cXMLNode,ret);
1300
- else
1301
- obj=(VALUE)ret->_private;
1302
-
1303
- return obj;
1304
- }
1305
-
1306
-
1307
- /*
1308
- * call-seq:
1309
- * node.space_preserve -> (true|false)
1310
- *
1311
- * Determine whether this node preserves whitespace.
1312
- */
1313
- VALUE
1314
- ruby_xml_node_space_preserve_get(VALUE self) {
1315
- xmlNodePtr xnode;
1316
-
1317
- Data_Get_Struct(self, xmlNode, xnode);
1318
- return(INT2NUM(xmlNodeGetSpacePreserve(xnode)));
1319
- }
1320
-
1321
-
1322
- /*
1323
- * call-seq:
1324
- * node.space_preserve = true|false
1325
- *
1326
- * Control whether this node preserves whitespace.
1327
- */
1328
- VALUE
1329
- ruby_xml_node_space_preserve_set(VALUE self, VALUE bool) {
1330
- xmlNodePtr xnode;
1331
- Data_Get_Struct(self, xmlNode, xnode);
1332
-
1333
- if (TYPE(bool) == T_FALSE)
1334
- xmlNodeSetSpacePreserve(xnode, 1);
1335
- else
1336
- xmlNodeSetSpacePreserve(xnode, 0);
1337
-
1338
- return(Qnil);
1339
- }
1340
-
1341
- /*
1342
- * call-seq:
1343
- * node.to_s -> "string"
1344
- *
1345
- * Coerce this node to a string representation of
1346
- * it's XML.
1347
- */
1348
- VALUE
1349
- ruby_xml_node_to_s(VALUE self) {
1350
- xmlNodePtr xnode;
1351
- xmlBufferPtr buf;
1352
- VALUE result;
1353
-
1354
- Data_Get_Struct(self, xmlNode, xnode);
1355
- buf = xmlBufferCreate();
1356
- xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
1357
- result = rb_str_new2((const char*)buf->content);
1358
-
1359
- xmlBufferFree(buf);
1360
- return result;
1361
- }
1362
-
1363
-
1364
- /*
1365
- * call-seq:
1366
- * node.type -> num
1367
- *
1368
- * Obtain this node's type identifier.
1369
- */
1370
- VALUE
1371
- ruby_xml_node_type(VALUE self) {
1372
- xmlNodePtr xnode;
1373
- Data_Get_Struct(self, xmlNode, xnode);
1374
- return(INT2NUM(xnode->type));
1375
- }
1376
-
1377
-
1378
-
1379
-
1380
- /*
1381
- * call-seq:
1382
- * node.copy -> XML::Node
1383
- *
1384
- * Creates a copy of this node. To create a
1385
- * shallow copy set the deep parameter to false.
1386
- * To create a deep copy set the deep parameter
1387
- * to true.
1388
- *
1389
- */
1390
- VALUE
1391
- ruby_xml_node_copy(VALUE self, VALUE deep) {
1392
- xmlNodePtr xnode;
1393
- xmlNodePtr xcopy;
1394
- int recursive = (deep==Qnil || deep==Qfalse) ? 0 : 1;
1395
- Data_Get_Struct(self, xmlNode, xnode);
1396
-
1397
- xcopy = xmlCopyNode(xnode, recursive);
1398
-
1399
- if (xcopy)
1400
- return ruby_xml_node2_wrap(cXMLNode, xcopy);
1401
- else
1402
- return Qnil;
1403
- }
1404
-
1405
- /*
1406
- * call-seq:
1407
- * XML::Node.new_text(content = nil) -> XML::Node
1408
- *
1409
- * Create a new text node, optionally setting
1410
- * the node's content.
1411
- *
1412
- */
1413
- VALUE
1414
- ruby_xml_node_new_text(VALUE class, VALUE text)
1415
- {
1416
- VALUE obj;
1417
- xmlNodePtr xnode;
1418
-
1419
- if ( NIL_P(text) )
1420
- return Qnil;
1421
-
1422
- if (TYPE(text) != T_STRING )
1423
- rb_raise(rb_eTypeError, "requires string argument");
1424
-
1425
- xnode=xmlNewText((xmlChar*)STR2CSTR(text));
1426
- if ( xnode == NULL )
1427
- return Qnil;
1428
-
1429
- obj=ruby_xml_node2_wrap(class,xnode);
1430
- rb_obj_call_init(obj,0,NULL);
1431
- return obj;
1432
- }
1433
-
1434
- void
1435
- ruby_xml_node_registerNode(xmlNodePtr node)
1436
- {
1437
- node->_private=NULL;
1438
- }
1439
-
1440
- void
1441
- ruby_xml_node_deregisterNode(xmlNodePtr xnode)
1442
- {
1443
- VALUE node;
1444
-
1445
- if (xnode->_private==NULL ) return;
1446
- node = (VALUE)xnode->_private;
1447
- DATA_PTR(node) = NULL;
1448
- }
1449
-
1450
- // Rdoc needs to know
1451
- #ifdef RDOC_NEVER_DEFINED
1452
- mLibXML = rb_define_module("LibXML");
1453
- mXML = rb_define_module_under(mLibXML, "XML");
1454
- #endif
1455
-
1456
- void
1457
- ruby_init_xml_node(void) {
1458
- xmlRegisterNodeDefault(ruby_xml_node_registerNode);
1459
- xmlDeregisterNodeDefault(ruby_xml_node_deregisterNode);
1460
-
1461
- cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
1462
- eXMLNodeSetNamespace = rb_define_class_under(cXMLNode, "SetNamespace", eXMLError);
1463
- eXMLNodeFailedModify = rb_define_class_under(cXMLNode, "FailedModify", eXMLError);
1464
- eXMLNodeUnknownType = rb_define_class_under(cXMLNode, "UnknownType", eXMLError);
1465
-
1466
- rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
1467
- rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
1468
- rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
1469
- rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
1470
- rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
1471
- rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
1472
- rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
1473
- rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
1474
- rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
1475
- rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
1476
- rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
1477
- rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
1478
- rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
1479
- rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
1480
-
1481
- rb_define_const(cXMLNode, "ELEMENT_NODE", INT2FIX(XML_ELEMENT_NODE));
1482
- rb_define_const(cXMLNode, "ATTRIBUTE_NODE", INT2FIX(XML_ATTRIBUTE_NODE));
1483
- rb_define_const(cXMLNode, "TEXT_NODE", INT2FIX(XML_TEXT_NODE));
1484
- rb_define_const(cXMLNode, "CDATA_SECTION_NODE", INT2FIX(XML_CDATA_SECTION_NODE));
1485
- rb_define_const(cXMLNode, "ENTITY_REF_NODE", INT2FIX(XML_ENTITY_REF_NODE));
1486
- rb_define_const(cXMLNode, "ENTITY_NODE", INT2FIX(XML_ENTITY_NODE));
1487
- rb_define_const(cXMLNode, "PI_NODE", INT2FIX(XML_PI_NODE));
1488
- rb_define_const(cXMLNode, "COMMENT_NODE", INT2FIX(XML_COMMENT_NODE));
1489
- rb_define_const(cXMLNode, "DOCUMENT_NODE", INT2FIX(XML_DOCUMENT_NODE));
1490
- rb_define_const(cXMLNode, "DOCUMENT_TYPE_NODE", INT2FIX(XML_DOCUMENT_TYPE_NODE));
1491
- rb_define_const(cXMLNode, "DOCUMENT_FRAG_NODE", INT2FIX(XML_DOCUMENT_FRAG_NODE));
1492
- rb_define_const(cXMLNode, "NOTATION_NODE", INT2FIX(XML_NOTATION_NODE));
1493
- rb_define_const(cXMLNode, "HTML_DOCUMENT_NODE", INT2FIX(XML_HTML_DOCUMENT_NODE));
1494
- rb_define_const(cXMLNode, "DTD_NODE", INT2FIX(XML_DTD_NODE));
1495
- rb_define_const(cXMLNode, "ELEMENT_DECL", INT2FIX(XML_ELEMENT_DECL));
1496
- rb_define_const(cXMLNode, "ATTRIBUTE_DECL", INT2FIX(XML_ATTRIBUTE_DECL));
1497
- rb_define_const(cXMLNode, "ENTITY_DECL", INT2FIX(XML_ENTITY_DECL));
1498
- rb_define_const(cXMLNode, "NAMESPACE_DECL", INT2FIX(XML_NAMESPACE_DECL));
1499
- rb_define_const(cXMLNode, "XINCLUDE_START", INT2FIX(XML_XINCLUDE_START));
1500
- rb_define_const(cXMLNode, "XINCLUDE_END", INT2FIX(XML_XINCLUDE_END));
1501
-
1502
- #ifdef LIBXML_DOCB_ENABLED
1503
- rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", INT2FIX(XML_DOCB_DOCUMENT_NODE));
1504
- #else
1505
- rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", Qnil);
1506
- #endif
1507
-
1508
-
1509
- rb_define_singleton_method(cXMLNode, "new2", ruby_xml_node2_new_native, 2);
1510
- rb_define_singleton_method(cXMLNode, "new", ruby_xml_node2_new_string_bc, -1);
1511
- rb_define_singleton_method(cXMLNode, "new_cdata", ruby_xml_node_new_cdata, -1);
1512
- rb_define_singleton_method(cXMLNode, "new_comment", ruby_xml_node_new_comment, -1);
1513
- rb_define_singleton_method(cXMLNode, "new_text", ruby_xml_node_new_text, 1);
1514
-
1515
- /* Traversal */
1516
- rb_include_module(cXMLNode, rb_mEnumerable);
1517
- rb_define_method(cXMLNode, "[]", ruby_xml_node_property_get, 1);
1518
- rb_define_method(cXMLNode, "each", ruby_xml_node_each, 0);
1519
- rb_define_method(cXMLNode, "first", ruby_xml_node_first_get, 0);
1520
- rb_define_method(cXMLNode, "last", ruby_xml_node_last_get, 0);
1521
- rb_define_method(cXMLNode, "next", ruby_xml_node_next_get, 0);
1522
- rb_define_method(cXMLNode, "parent", ruby_xml_node_parent_get, 0);
1523
- rb_define_method(cXMLNode, "prev", ruby_xml_node_prev_get, 0);
1524
-
1525
- /* Modification */
1526
- rb_define_method(cXMLNode, "<<", ruby_xml_node_content_add, 1);
1527
- rb_define_method(cXMLNode, "[]=", ruby_xml_node_property_set, 2);
1528
- rb_define_method(cXMLNode, "child_add", ruby_xml_node_child_add, 1);
1529
- rb_define_method(cXMLNode, "child=", ruby_xml_node_child_set, 1);
1530
- rb_define_method(cXMLNode, "sibling=", ruby_xml_node_sibling_set, 1);
1531
- rb_define_method(cXMLNode, "next=", ruby_xml_node_next_set, 1);
1532
- rb_define_method(cXMLNode, "prev=", ruby_xml_node_prev_set, 1);
1533
-
1534
-
1535
- /* Rest of the node api */
1536
- rb_define_method(cXMLNode, "attributes", ruby_xml_node_attributes_get, 0);
1537
- rb_define_method(cXMLNode, "base", ruby_xml_node_base_get, 0);
1538
- rb_define_method(cXMLNode, "base=", ruby_xml_node_base_set, 1);
1539
- rb_define_method(cXMLNode, "blank?", ruby_xml_node_empty_q, 0);
1540
- rb_define_method(cXMLNode, "copy", ruby_xml_node_copy, 1);
1541
- rb_define_method(cXMLNode, "content", ruby_xml_node_content_get, 0);
1542
- rb_define_method(cXMLNode, "content=", ruby_xml_node_content_set, 1);
1543
- rb_define_method(cXMLNode, "content_stripped", ruby_xml_node_content_stripped_get, 0);
1544
- rb_define_method(cXMLNode, "doc", ruby_xml_node_doc, 0);
1545
- rb_define_method(cXMLNode, "dump", ruby_xml_node_dump, 0);
1546
- rb_define_method(cXMLNode, "debug_dump", ruby_xml_node_debug_dump, 0);
1547
- rb_define_method(cXMLNode, "empty?", ruby_xml_node_empty_q, 0);
1548
- rb_define_method(cXMLNode, "eql?", ruby_xml_node_eql_q, 1);
1549
- rb_define_method(cXMLNode, "lang", ruby_xml_node_lang_get, 0);
1550
- rb_define_method(cXMLNode, "lang=", ruby_xml_node_lang_set, 1);
1551
- rb_define_method(cXMLNode, "line_num", ruby_xml_node_line_num, 0);
1552
- rb_define_method(cXMLNode, "name", ruby_xml_node_name_get, 0);
1553
- rb_define_method(cXMLNode, "name=", ruby_xml_node_name_set, 1);
1554
- rb_define_method(cXMLNode, "namespace", ruby_xml_node_namespace_get, 0);
1555
- rb_define_method(cXMLNode, "namespace_node", ruby_xml_node_namespace_get_node, 0);
1556
- rb_define_method(cXMLNode, "namespace=", ruby_xml_node_namespace_set, -1);
1557
- rb_define_method(cXMLNode, "node_type", ruby_xml_node_type, 0);
1558
- rb_define_method(cXMLNode, "ns", ruby_xml_node_namespace_get, 0);
1559
- rb_define_method(cXMLNode, "ns?", ruby_xml_node_ns_q, 0);
1560
- rb_define_method(cXMLNode, "ns_def?", ruby_xml_node_ns_def_q, 0);
1561
- rb_define_method(cXMLNode, "ns_def", ruby_xml_node_ns_def_get, 0);
1562
- rb_define_method(cXMLNode, "path", ruby_xml_node_path, 0);
1563
- rb_define_method(cXMLNode, "pointer", ruby_xml_node_pointer, 1);
1564
- rb_define_method(cXMLNode, "remove!", ruby_xml_node_remove_ex, 0);
1565
- rb_define_method(cXMLNode, "search_ns", ruby_xml_node_search_ns, 1);
1566
- rb_define_method(cXMLNode, "search_href", ruby_xml_node_search_href, 1);
1567
- rb_define_method(cXMLNode, "space_preserve", ruby_xml_node_space_preserve_get, 0);
1568
- rb_define_method(cXMLNode, "space_preserve=", ruby_xml_node_space_preserve_set, 1);
1569
- rb_define_method(cXMLNode, "to_s", ruby_xml_node_to_s, 0);
1570
- rb_define_method(cXMLNode, "xlink?", ruby_xml_node_xlink_q, 0);
1571
- rb_define_method(cXMLNode, "xlink_type", ruby_xml_node_xlink_type, 0);
1572
- rb_define_method(cXMLNode, "xlink_type_name", ruby_xml_node_xlink_type_name, 0);
1573
-
1574
- rb_define_alias(cXMLNode, "==", "eql?");
1575
-
1576
- /* :nodoc: */
1577
- {
1578
- VALUE singleton;
1579
- singleton = rb_singleton_class(cXMLNode);
1580
- rb_define_alias(singleton, "new_element", "new");
1581
- }
1582
- }
1
+ /* $Id: ruby_xml_node.c 560 2008-11-18 04:09:19Z cfis $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "ruby_libxml.h"
6
+ #include "ruby_xml_node.h"
7
+
8
+ VALUE cXMLNode;
9
+
10
+ /* Document-class: LibXML::XML::Node
11
+ *
12
+ * Nodes are the primary objects that make up an XML document.
13
+ * The node class represents most node types that are found in
14
+ * an XML document (but not Attributes, see LibXML::XML::Attribute).
15
+ * It exposes libxml's full API for creating, querying
16
+ * moving and deleting node objects. Many of these methods are
17
+ * documented in the DOM Level 3 specification found at:
18
+ * http://www.w3.org/TR/DOM-Level-3-Core/. */
19
+
20
+
21
+ VALUE
22
+ check_string_or_symbol( VALUE val ) {
23
+ if( TYPE(val) != T_STRING && TYPE(val) != T_SYMBOL ) {
24
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Symbol)",
25
+ rb_obj_classname(val) );
26
+ }
27
+ return rb_obj_as_string( val );
28
+ }
29
+
30
+
31
+ /*
32
+ * call-seq:
33
+ * node.base -> "uri"
34
+ *
35
+ * Obtain this node's base URI.
36
+ */
37
+ VALUE
38
+ ruby_xml_node_base_get(VALUE self) {
39
+ xmlNodePtr xnode;
40
+ xmlChar* base_uri;
41
+ VALUE result = Qnil;
42
+
43
+ Data_Get_Struct(self, xmlNode, xnode);
44
+
45
+ if (xnode->doc == NULL)
46
+ return(result);
47
+
48
+ base_uri = xmlNodeGetBase(xnode->doc, xnode);
49
+ if (base_uri) {
50
+ result = rb_str_new2((const char*)base_uri);
51
+ xmlFree(base_uri);
52
+ }
53
+
54
+ return(result);
55
+ }
56
+
57
+
58
+ // TODO node_base_set should support setting back to nil
59
+
60
+ /*
61
+ * call-seq:
62
+ * node.base = "uri"
63
+ *
64
+ * Set this node's base URI.
65
+ */
66
+ VALUE
67
+ ruby_xml_node_base_set(VALUE self, VALUE uri) {
68
+ xmlNodePtr xnode;
69
+
70
+ Check_Type(uri, T_STRING);
71
+ Data_Get_Struct(self, xmlNode, xnode);
72
+ if (xnode->doc == NULL)
73
+ return(Qnil);
74
+
75
+ xmlNodeSetBase(xnode, (xmlChar*)StringValuePtr(uri));
76
+ return(Qtrue);
77
+ }
78
+
79
+
80
+ /*
81
+ * call-seq:
82
+ * node.content -> "string"
83
+ *
84
+ * Obtain this node's content as a string.
85
+ */
86
+ VALUE
87
+ ruby_xml_node_content_get(VALUE self) {
88
+ xmlNodePtr xnode;
89
+ xmlChar *content;
90
+ VALUE result = Qnil;
91
+
92
+ Data_Get_Struct(self, xmlNode, xnode);
93
+ content = xmlNodeGetContent(xnode);
94
+ if (content) {
95
+ result = rb_str_new2((const char *) content);
96
+ xmlFree(content);
97
+ }
98
+
99
+ return result;
100
+ }
101
+
102
+ /*
103
+ * call-seq:
104
+ * node.content = "string"
105
+ *
106
+ * Set this node's content to the specified string.
107
+ */
108
+ VALUE
109
+ ruby_xml_node_content_set(VALUE self, VALUE content) {
110
+ xmlNodePtr xnode;
111
+
112
+ Check_Type(content, T_STRING);
113
+ Data_Get_Struct(self, xmlNode, xnode);
114
+ // XXX docs indicate need for escaping entites, need to be done? danj
115
+ xmlNodeSetContent(xnode, (xmlChar*)StringValuePtr(content));
116
+ return(Qtrue);
117
+ }
118
+
119
+
120
+ /*
121
+ * call-seq:
122
+ * node.content_stripped -> "string"
123
+ *
124
+ * Obtain this node's stripped content.
125
+ *
126
+ * *Deprecated*: Stripped content can be obtained via the
127
+ * +content+ method.
128
+ */
129
+ VALUE
130
+ ruby_xml_node_content_stripped_get(VALUE self) {
131
+ xmlNodePtr xnode;
132
+ xmlChar* content;
133
+ VALUE result = Qnil;
134
+
135
+ Data_Get_Struct(self, xmlNode, xnode);
136
+
137
+ if (!xnode->content)
138
+ return result;
139
+
140
+ content = xmlNodeGetContent(xnode);
141
+ if (content) {
142
+ result = rb_str_new2((const char*)content);
143
+ xmlFree(content);
144
+ }
145
+ return(result);
146
+ }
147
+
148
+ /*
149
+ * call-seq:
150
+ * node.first -> XML::Node
151
+ *
152
+ * Returns this node's first child node if any.
153
+ */
154
+ VALUE
155
+ ruby_xml_node_first_get(VALUE self) {
156
+ xmlNodePtr xnode;
157
+
158
+ Data_Get_Struct(self, xmlNode, xnode);
159
+
160
+ if (xnode->children)
161
+ return(ruby_xml_node2_wrap(cXMLNode, xnode->children));
162
+ else
163
+ return(Qnil);
164
+ }
165
+
166
+
167
+ /*
168
+ * underlying for child_set and child_add, difference being
169
+ * former raises on implicit copy, latter does not.
170
+ */
171
+ VALUE
172
+ ruby_xml_node_child_set_aux(VALUE self, VALUE rnode) {
173
+ xmlNodePtr pnode, chld, ret;
174
+
175
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
176
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
177
+
178
+ Data_Get_Struct(self, xmlNode, pnode);
179
+ Data_Get_Struct(rnode, xmlNode, chld);
180
+
181
+ if ( chld->parent != NULL || chld->doc != NULL )
182
+ rb_raise(rb_eRuntimeError, "Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
183
+
184
+ ret = xmlAddChild(pnode, chld);
185
+ if (ret == NULL) {
186
+ ruby_xml_raise(&xmlLastError);
187
+ } else if ( ret==chld ) {
188
+ /* child was added whole to parent and we need to return it as a new object */
189
+ return ruby_xml_node2_wrap(cXMLNode,chld);
190
+ }
191
+ /* else */
192
+ /* If it was a text node, then ret should be parent->last, so we will just return ret. */
193
+ return ruby_xml_node2_wrap(cXMLNode,ret);
194
+ }
195
+
196
+ /*
197
+ * call-seq:
198
+ * node.child = node
199
+ *
200
+ * Set a child node for this node. Also called for <<
201
+ */
202
+ VALUE
203
+ ruby_xml_node_child_set(VALUE self, VALUE rnode) {
204
+ return ruby_xml_node_child_set_aux(self, rnode);
205
+ }
206
+
207
+
208
+ /*
209
+ * call-seq:
210
+ * node << ("string" | node) -> XML::Node
211
+ *
212
+ * Add the specified string or XML::Node to this node's
213
+ * content. The returned node is the node that was
214
+ * added and not self, thereby allowing << calls to
215
+ * be chained.
216
+ */
217
+ VALUE
218
+ ruby_xml_node_content_add(VALUE self, VALUE obj) {
219
+ xmlNodePtr xnode;
220
+ VALUE str;
221
+
222
+ Data_Get_Struct(self, xmlNode, xnode);
223
+ /* XXX This should only be legal for a CDATA type node, I think,
224
+ * resulting in a merge of content, as if a string were passed
225
+ * danj 070827
226
+ */
227
+ if (rb_obj_is_kind_of(obj, cXMLNode)) {
228
+ ruby_xml_node_child_set(self, obj);
229
+ } else {
230
+ str = rb_obj_as_string(obj);
231
+ if (NIL_P(str) || TYPE(str) != T_STRING)
232
+ rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
233
+
234
+ xmlNodeAddContent(xnode, (xmlChar*)StringValuePtr(str));
235
+ }
236
+ return(self);
237
+ }
238
+
239
+ /*
240
+ * call-seq:
241
+ * node.child_add(node)
242
+ *
243
+ * Set a child node for this node.
244
+ */
245
+ VALUE
246
+ ruby_xml_node_child_add(VALUE self, VALUE rnode) {
247
+ return ruby_xml_node_child_set_aux(self, rnode);
248
+ }
249
+
250
+ /*
251
+ * call-seq:
252
+ * node.doc -> document
253
+ *
254
+ * Obtain the XML::Document this node belongs to.
255
+ */
256
+ VALUE
257
+ ruby_xml_node_doc(VALUE self) {
258
+ xmlNodePtr xnode;
259
+ xmlDocPtr doc=NULL;
260
+
261
+ Data_Get_Struct(self, xmlNode, xnode);
262
+
263
+ switch (xnode->type) {
264
+ case XML_DOCUMENT_NODE:
265
+ #ifdef LIBXML_DOCB_ENABLED
266
+ case XML_DOCB_DOCUMENT_NODE:
267
+ #endif
268
+ case XML_HTML_DOCUMENT_NODE:
269
+ doc = NULL;
270
+ break;
271
+ case XML_ATTRIBUTE_NODE:
272
+ {
273
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
274
+ doc = attr->doc;
275
+ break;
276
+ }
277
+ case XML_NAMESPACE_DECL:
278
+ doc = NULL;
279
+ break;
280
+ default:
281
+ doc = xnode->doc;
282
+ break;
283
+ }
284
+
285
+ if (doc == NULL)
286
+ return(Qnil);
287
+
288
+ if ( doc->_private == NULL )
289
+ rb_raise(rb_eRuntimeError,"existing document object has no ruby-instance");
290
+
291
+ return (VALUE)doc->_private;
292
+ }
293
+
294
+
295
+ /*
296
+ * call-seq:
297
+ * node.dump -> (true|nil)
298
+ *
299
+ * Dump this node to stdout.
300
+ */
301
+ VALUE
302
+ ruby_xml_node_dump(VALUE self) {
303
+ xmlNodePtr xnode;
304
+ xmlBufferPtr buf;
305
+
306
+ Data_Get_Struct(self, xmlNode, xnode);
307
+
308
+ if (xnode->doc == NULL)
309
+ return(Qnil);
310
+
311
+ buf = xmlBufferCreate();
312
+ xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
313
+ xmlBufferDump(stdout, buf);
314
+ xmlBufferFree(buf);
315
+ return(Qtrue);
316
+ }
317
+
318
+
319
+ /*
320
+ * call-seq:
321
+ * node.debug_dump -> (true|nil)
322
+ *
323
+ * Dump this node to stdout, including any debugging
324
+ * information.
325
+ */
326
+ VALUE
327
+ ruby_xml_node_debug_dump(VALUE self) {
328
+ xmlNodePtr xnode;
329
+ Data_Get_Struct(self, xmlNode, xnode);
330
+
331
+ if (xnode->doc == NULL)
332
+ return(Qnil);
333
+
334
+ xmlElemDump(stdout, xnode->doc, xnode);
335
+ return(Qtrue);
336
+ }
337
+
338
+ /*
339
+ * call-seq:
340
+ * node.each -> XML::Node
341
+ *
342
+ * Iterates over this node's children, including text
343
+ * nodes, element nodes, etc. If you wish to iterate
344
+ * only over child elements, use XML::Node#each_element.
345
+ *
346
+ * doc = XML::Document.new('model/books.xml')
347
+ * doc.root.each {|node| puts node}
348
+ */
349
+ VALUE
350
+ ruby_xml_node_each(VALUE self) {
351
+ xmlNodePtr xnode;
352
+ xmlNodePtr xchild;
353
+ Data_Get_Struct(self, xmlNode, xnode);
354
+
355
+ xchild = xnode->children;
356
+
357
+ while (xchild) {
358
+ rb_yield(ruby_xml_node2_wrap(cXMLNode, xchild));
359
+ xchild = xchild->next;
360
+ }
361
+ return Qnil;
362
+ }
363
+
364
+
365
+ /*
366
+ * call-seq:
367
+ * node.empty? -> (true|false)
368
+ *
369
+ * Determine whether this node is empty.
370
+ */
371
+ VALUE
372
+ ruby_xml_node_empty_q(VALUE self) {
373
+ xmlNodePtr xnode;
374
+ Data_Get_Struct(self, xmlNode, xnode);
375
+ if (xnode == NULL)
376
+ return(Qnil);
377
+
378
+ return((xmlIsBlankNode(xnode) == 1) ? Qtrue : Qfalse);
379
+ }
380
+
381
+
382
+ VALUE ruby_xml_node_to_s(VALUE self);
383
+
384
+ /*
385
+ * call-seq:
386
+ * node.eql?(other_node) => (true|false)
387
+ *
388
+ * Test equality between the two nodes. Two nodes are equal
389
+ * if they are the same node or have the same XML representation.*/
390
+ VALUE
391
+ ruby_xml_node_eql_q(VALUE self, VALUE other) {
392
+ if (self == other)
393
+ {
394
+ return Qtrue;
395
+ }
396
+ else if NIL_P(other)
397
+ {
398
+ return Qfalse;
399
+ }
400
+ else
401
+ {
402
+ VALUE self_xml;
403
+ VALUE other_xml;
404
+
405
+ if (rb_obj_is_kind_of(other, cXMLNode) == Qfalse)
406
+ rb_raise(rb_eTypeError, "Nodes can only be compared against other nodes");
407
+
408
+ self_xml = ruby_xml_node_to_s(self);
409
+ other_xml = ruby_xml_node_to_s(other);
410
+ return(rb_funcall(self_xml, rb_intern("=="), 1, other_xml));
411
+ }
412
+ }
413
+
414
+ /*
415
+ * call-seq:
416
+ * XML::Node.new_cdata(content = nil) -> XML::Node
417
+ *
418
+ * Create a new #CDATA node, optionally setting
419
+ * the node's content.
420
+ */
421
+ VALUE
422
+ ruby_xml_node_new_cdata(int argc, VALUE *argv, VALUE class) {
423
+ xmlNodePtr xnode;
424
+ VALUE str=Qnil;
425
+
426
+ switch(argc) {
427
+ case 1:
428
+ str = argv[0];
429
+ Check_Type(str, T_STRING);
430
+ if (!NIL_P(str)) {
431
+ xnode = xmlNewCDataBlock(NULL, (xmlChar*)StringValuePtr(str), xmlStrlen((xmlChar*)StringValuePtr(str)));
432
+ } else {
433
+ xnode = xmlNewCDataBlock(NULL, NULL , 0);
434
+ }
435
+
436
+ if (xnode == NULL)
437
+ return(Qnil);
438
+
439
+ return ruby_xml_node2_wrap(class,xnode);
440
+
441
+ default:
442
+ rb_raise(rb_eArgError, "wrong number of arguments (1)");
443
+ }
444
+
445
+ // not reached
446
+ return(Qnil);
447
+ }
448
+
449
+
450
+ /*
451
+ * call-seq:
452
+ * XML::Node.new_comment(content = nil) -> XML::Node
453
+ *
454
+ * Create a new comment node, optionally setting
455
+ * the node's content.
456
+ *
457
+ */
458
+ VALUE
459
+ ruby_xml_node_new_comment(int argc, VALUE *argv, VALUE class) {
460
+ xmlNodePtr xnode;
461
+ VALUE str=Qnil;
462
+
463
+ switch(argc) {
464
+ case 1:
465
+ str = argv[0];
466
+ Check_Type(str, T_STRING);
467
+ // TODO xmlNewComment wrongly? adds \n before and after the comment
468
+ if (!NIL_P(str)) {
469
+ xnode = xmlNewComment((xmlChar*)StringValuePtr(str));
470
+ } else {
471
+ xnode = xmlNewComment(NULL);
472
+ }
473
+
474
+ if (xnode == NULL)
475
+ return(Qnil);
476
+
477
+ return ruby_xml_node2_wrap(class,xnode);
478
+
479
+ default:
480
+ rb_raise(rb_eArgError, "wrong number of arguments (1)");
481
+ }
482
+
483
+ // not reached
484
+ return(Qnil);
485
+ }
486
+
487
+
488
+ /*
489
+ * call-seq:
490
+ * node.lang -> "string"
491
+ *
492
+ * Obtain the language set for this node, if any.
493
+ * This is set in XML via the xml:lang attribute.
494
+ */
495
+ VALUE
496
+ ruby_xml_node_lang_get(VALUE self) {
497
+ xmlNodePtr xnode;
498
+ xmlChar *lang;
499
+ VALUE result = Qnil;
500
+
501
+ Data_Get_Struct(self, xmlNode, xnode);
502
+ lang = xmlNodeGetLang(xnode);
503
+
504
+ if (lang) {
505
+ result = rb_str_new2((const char*)lang);
506
+ xmlFree(lang);
507
+ }
508
+
509
+ return(result);
510
+ }
511
+
512
+
513
+ // TODO node_lang_set should support setting back to nil
514
+
515
+ /*
516
+ * call-seq:
517
+ * node.lang = "string"
518
+ *
519
+ * Set the language for this node. This affects the value
520
+ * of the xml:lang attribute.
521
+ */
522
+ VALUE
523
+ ruby_xml_node_lang_set(VALUE self, VALUE lang) {
524
+ xmlNodePtr xnode;
525
+
526
+ Check_Type(lang, T_STRING);
527
+ Data_Get_Struct(self, xmlNode, xnode);
528
+ xmlNodeSetLang(xnode, (xmlChar*)StringValuePtr(lang));
529
+
530
+ return(Qtrue);
531
+ }
532
+
533
+
534
+ /*
535
+ * call-seq:
536
+ * node.last -> XML::Node
537
+ *
538
+ * Obtain the last child node of this node, if any.
539
+ */
540
+ VALUE
541
+ ruby_xml_node_last_get(VALUE self) {
542
+ xmlNodePtr xnode;
543
+
544
+ Data_Get_Struct(self, xmlNode, xnode);
545
+
546
+ if (xnode->last)
547
+ return(ruby_xml_node2_wrap(cXMLNode, xnode->last));
548
+ else
549
+ return(Qnil);
550
+ }
551
+
552
+ /*
553
+ * call-seq:
554
+ * node.line_num -> num
555
+ *
556
+ * Obtain the line number (in the XML document) that this
557
+ * node was read from. If +default_line_numbers+ is set
558
+ * false (the default), this method returns zero.
559
+ */
560
+ VALUE
561
+ ruby_xml_node_line_num(VALUE self) {
562
+ xmlNodePtr xnode;
563
+ long line_num;
564
+ Data_Get_Struct(self, xmlNode, xnode);
565
+
566
+ if (!xmlLineNumbersDefaultValue)
567
+ rb_warn("Line numbers were not retained: use XML::Parser::default_line_numbers=true");
568
+
569
+ line_num = xmlGetLineNo(xnode);
570
+ if (line_num == -1)
571
+ return(Qnil);
572
+ else
573
+ return(INT2NUM((long)line_num));
574
+ }
575
+
576
+
577
+ /*
578
+ * call-seq:
579
+ * node.xlink? -> (true|false)
580
+ *
581
+ * Determine whether this node is an xlink node.
582
+ */
583
+ VALUE
584
+ ruby_xml_node_xlink_q(VALUE self) {
585
+ xmlNodePtr xnode;
586
+ xlinkType xlt;
587
+
588
+ Data_Get_Struct(self, xmlNode, xnode);
589
+ xlt = xlinkIsLink(xnode->doc, xnode);
590
+
591
+ if (xlt == XLINK_TYPE_NONE)
592
+ return(Qfalse);
593
+ else
594
+ return(Qtrue);
595
+ }
596
+
597
+
598
+ /*
599
+ * call-seq:
600
+ * node.xlink_type -> num
601
+ *
602
+ * Obtain the type identifier for this xlink, if applicable.
603
+ * If this is not an xlink node (see +xlink?+), will return
604
+ * nil.
605
+ */
606
+ VALUE
607
+ ruby_xml_node_xlink_type(VALUE self) {
608
+ xmlNodePtr xnode;
609
+ xlinkType xlt;
610
+
611
+ Data_Get_Struct(self, xmlNode, xnode);
612
+ xlt = xlinkIsLink(xnode->doc, xnode);
613
+
614
+ if (xlt == XLINK_TYPE_NONE)
615
+ return(Qnil);
616
+ else
617
+ return(INT2NUM(xlt));
618
+ }
619
+
620
+
621
+ /*
622
+ * call-seq:
623
+ * node.xlink_type_name -> "string"
624
+ *
625
+ * Obtain the type name for this xlink, if applicable.
626
+ * If this is not an xlink node (see +xlink?+), will return
627
+ * nil.
628
+ */
629
+ VALUE
630
+ ruby_xml_node_xlink_type_name(VALUE self) {
631
+ xmlNodePtr xnode;
632
+ xlinkType xlt;
633
+
634
+ Data_Get_Struct(self, xmlNode, xnode);
635
+ xlt = xlinkIsLink(xnode->doc, xnode);
636
+
637
+ switch(xlt) {
638
+ case XLINK_TYPE_NONE:
639
+ return(Qnil);
640
+ case XLINK_TYPE_SIMPLE:
641
+ return(rb_str_new2("simple"));
642
+ case XLINK_TYPE_EXTENDED:
643
+ return(rb_str_new2("extended"));
644
+ case XLINK_TYPE_EXTENDED_SET:
645
+ return(rb_str_new2("extended_set"));
646
+ default:
647
+ rb_fatal("Unknowng xlink type, %d", xlt);
648
+ }
649
+ }
650
+
651
+ /*
652
+ * call-seq:
653
+ * node.name -> "string"
654
+ *
655
+ * Obtain this node's name.
656
+ */
657
+ VALUE
658
+ ruby_xml_node_name_get(VALUE self) {
659
+ xmlNodePtr xnode;
660
+ const xmlChar *name;
661
+
662
+ Data_Get_Struct(self, xmlNode, xnode);
663
+
664
+ switch (xnode->type) {
665
+ case XML_DOCUMENT_NODE:
666
+ #ifdef LIBXML_DOCB_ENABLED
667
+ case XML_DOCB_DOCUMENT_NODE:
668
+ #endif
669
+ case XML_HTML_DOCUMENT_NODE:
670
+ {
671
+ xmlDocPtr doc = (xmlDocPtr) xnode;
672
+ name = doc->URL;
673
+ break;
674
+ }
675
+ case XML_ATTRIBUTE_NODE:
676
+ {
677
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
678
+ name = attr->name;
679
+ break;
680
+ }
681
+ case XML_NAMESPACE_DECL:
682
+ {
683
+ xmlNsPtr ns = (xmlNsPtr) xnode;
684
+ name = ns->prefix;
685
+ break;
686
+ }
687
+ default:
688
+ name = xnode->name;
689
+ break;
690
+ }
691
+
692
+ if (xnode->name == NULL)
693
+ return(Qnil);
694
+ else
695
+ return(rb_str_new2((const char*)name));
696
+ }
697
+
698
+
699
+ /*
700
+ * call-seq:
701
+ * node.name = "string"
702
+ *
703
+ * Set this node's name.
704
+ */
705
+ VALUE
706
+ ruby_xml_node_name_set(VALUE self, VALUE name) {
707
+ xmlNodePtr xnode;
708
+
709
+ Check_Type(name, T_STRING);
710
+ Data_Get_Struct(self, xmlNode, xnode);
711
+ xmlNodeSetName(xnode, (xmlChar*)StringValuePtr(name));
712
+ return(Qtrue);
713
+ }
714
+
715
+
716
+ /*
717
+ * call-seq:
718
+ * node.namespace -> [namespace, ..., namespace]
719
+ *
720
+ * Obtain an array of +XML::NS+ objects representing
721
+ * this node's xmlns attributes
722
+ */
723
+ VALUE
724
+ ruby_xml_node_namespace_get(VALUE self) {
725
+ xmlNodePtr xnode;
726
+ xmlNsPtr *nsList, *cur;
727
+ VALUE arr, ns;
728
+
729
+ Data_Get_Struct(self, xmlNode, xnode);
730
+ if (xnode == NULL)
731
+ return(Qnil);
732
+
733
+ nsList = xmlGetNsList(xnode->doc, xnode);
734
+
735
+ if (nsList == NULL)
736
+ return(Qnil);
737
+
738
+ arr = rb_ary_new();
739
+ for (cur = nsList; *cur != NULL; cur++) {
740
+ ns = ruby_xml_ns_wrap(*cur);
741
+ if (ns == Qnil)
742
+ continue;
743
+ else
744
+ rb_ary_push(arr, ns);
745
+ }
746
+ xmlFree(nsList);
747
+
748
+ return(arr);
749
+ }
750
+
751
+
752
+ /*
753
+ * call-seq:
754
+ * node.namespace_node -> namespace.
755
+ *
756
+ * Obtain this node's namespace node.
757
+ */
758
+ VALUE
759
+ ruby_xml_node_namespace_get_node(VALUE self) {
760
+ xmlNodePtr xnode;
761
+
762
+ Data_Get_Struct(self, xmlNode, xnode);
763
+ if (xnode->ns == NULL)
764
+ return(Qnil);
765
+ else
766
+ return ruby_xml_ns_wrap(xnode->ns);
767
+ }
768
+
769
+ // TODO namespace_set can take varargs (in fact, must if used
770
+ // with strings), but I cannot see how you can call
771
+ // that version, apart from with 'send'
772
+ //
773
+ // Would sure be nice to support foo.namespace['foo'] = 'bar'
774
+ // but maybe that's not practical...
775
+
776
+ /*
777
+ * call-seq:
778
+ * node.namespace = namespace
779
+ *
780
+ * Add the specified XML::NS object to this node's xmlns attributes.
781
+ */
782
+ VALUE
783
+ ruby_xml_node_namespace_set(int argc, VALUE *argv, VALUE self) {
784
+ VALUE rns, rprefix;
785
+ xmlNodePtr xnode;
786
+ xmlNsPtr xns;
787
+ char *cp, *href;
788
+
789
+ Data_Get_Struct(self, xmlNode, xnode);
790
+ switch (argc) {
791
+ case 1:
792
+ rns = argv[0];
793
+ if (TYPE(rns) == T_STRING) {
794
+ cp = strchr(StringValuePtr(rns), (int)':');
795
+ if (cp == NULL) {
796
+ rprefix = rns;
797
+ href = NULL;
798
+ } else {
799
+ rprefix = rb_str_new(StringValuePtr(rns), (int)((long)cp - (long)StringValuePtr(rns)));
800
+ href = &cp[1]; /* skip the : */
801
+ }
802
+ } else if (rb_obj_is_kind_of(rns, cXMLNS) == Qtrue) {
803
+ Data_Get_Struct(self, xmlNs, xns);
804
+ xmlSetNs(xnode, xns);
805
+ return(rns);
806
+ } else
807
+ rb_raise(rb_eTypeError, "must pass a string or an XML::Ns object");
808
+
809
+ /* Fall through to next case because when argc == 1, we need to
810
+ * manually setup the additional args unless the arg passed is of
811
+ * cXMLNS type */
812
+ case 2:
813
+ /* Don't want this code run in the fall through case */
814
+ if (argc == 2) {
815
+ rprefix = argv[0];
816
+ href = StringValuePtr(argv[1]);
817
+ }
818
+
819
+ xns = xmlNewNs(xnode, (xmlChar*)href, (xmlChar*)StringValuePtr(rprefix));
820
+ if (xns == NULL)
821
+ ruby_xml_raise(&xmlLastError);
822
+ else
823
+ return ruby_xml_ns_wrap(xns);
824
+ break;
825
+
826
+ default:
827
+ rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
828
+ }
829
+
830
+ /* can't get here */
831
+ return(Qnil);
832
+ }
833
+
834
+
835
+ /*
836
+ * memory2 implementation: xmlNode->_private holds a reference
837
+ * to the wrapping ruby object VALUE when there is one.
838
+ * traversal for marking is upward, and top levels are marked
839
+ * through and lower level mark entry.
840
+ *
841
+ * All ruby retrieval for an xml
842
+ * node will result in the same ruby instance. When all handles to them
843
+ * go out of scope, then ruby_xfree gets called and _private is set to NULL.
844
+ * If the xmlNode has no parent or document, then call xmlFree.
845
+ */
846
+ void
847
+ ruby_xml_node2_free(xmlNodePtr xnode) {
848
+
849
+ if (xnode != NULL) {
850
+ xnode->_private=NULL;
851
+
852
+ if (xnode->doc==NULL && xnode->parent==NULL) {
853
+ xmlFreeNode(xnode);
854
+ }
855
+ }
856
+ }
857
+
858
+ void
859
+ ruby_xml_node_mark_common(xmlNodePtr xnode) {
860
+ if (xnode->parent == NULL ) {
861
+ #ifdef NODE_DEBUG
862
+ fprintf(stderr,"mark no parent r=0x%x *n=0x%x\n",rxn,node);
863
+ #endif
864
+ } else if (xnode->doc != NULL ) {
865
+ if (xnode->doc->_private == NULL) {
866
+ rb_bug("XmlNode Doc is not bound! (%s:%d)",
867
+ __FILE__,__LINE__);
868
+ }
869
+ rb_gc_mark((VALUE)xnode->doc->_private);
870
+ } else {
871
+ while (xnode->parent != NULL )
872
+ xnode = xnode->parent;
873
+ if (xnode->_private == NULL )
874
+ rb_warning("XmlNode Root Parent is not bound! (%s:%d)",
875
+ __FILE__,__LINE__);
876
+ else {
877
+ rb_gc_mark((VALUE)xnode->_private);
878
+ }
879
+ }
880
+ }
881
+
882
+ void
883
+ ruby_xml_node2_mark(xmlNodePtr xnode) {
884
+ if (xnode == NULL ) return;
885
+
886
+ if (xnode->_private == NULL ) {
887
+ rb_warning("XmlNode is not bound! (%s:%d)",
888
+ __FILE__,__LINE__);
889
+ return;
890
+ }
891
+
892
+ ruby_xml_node_mark_common(xnode);
893
+ }
894
+
895
+ VALUE
896
+ ruby_xml_node2_wrap(VALUE class, xmlNodePtr xnode)
897
+ {
898
+ VALUE obj;
899
+
900
+ // This node is already wrapped
901
+ if (xnode->_private != NULL) {
902
+ return (VALUE)xnode->_private;
903
+ }
904
+
905
+ obj=Data_Wrap_Struct(class,
906
+ ruby_xml_node2_mark, ruby_xml_node2_free,
907
+ xnode);
908
+
909
+ xnode->_private=(void*)obj;
910
+ return obj;
911
+ }
912
+
913
+ /*
914
+ * call-seq:
915
+ * XML::Node.new_string(namespace, name, content) -> XML::Node
916
+ *
917
+ * Create a new element node in the specified namespace with the
918
+ * supplied name and content.
919
+ */
920
+ VALUE
921
+ ruby_xml_node_new_string(VALUE klass, VALUE ns, VALUE name, VALUE val)
922
+ {
923
+ xmlNodePtr xnode;
924
+ xmlNsPtr xns = NULL;
925
+ VALUE node;
926
+
927
+ if (!NIL_P(ns)) {
928
+ Data_Get_Struct(ns, xmlNs, xns);
929
+ }
930
+
931
+ xnode = xmlNewNode(xns,(xmlChar*)StringValuePtr(name));
932
+ xnode->_private=NULL;
933
+
934
+ node = ruby_xml_node2_wrap(klass, xnode);
935
+ rb_obj_call_init(node, 0, NULL);
936
+
937
+ if (!NIL_P(val))
938
+ {
939
+ if (TYPE(val) != T_STRING)
940
+ val = rb_obj_as_string(val);
941
+
942
+ ruby_xml_node_content_set(node, val);
943
+ }
944
+ return node;
945
+ }
946
+
947
+ /*
948
+ * call-seq:
949
+ * XML::Node.new(name, content = nil) -> XML::Node
950
+ * XML::Node.new_element(name, content = nil) -> XML::Node
951
+ *
952
+ * Create a new element node with the specified name, optionally setting
953
+ * the node's content.
954
+ * backward compatibility for <.5 new
955
+ */
956
+ VALUE
957
+ ruby_xml_node_new_string_bc(int argc, VALUE *argv, VALUE class)
958
+ {
959
+ VALUE content=Qnil;
960
+ VALUE name=Qnil;
961
+ switch(argc) {
962
+ case 2:
963
+ content=argv[1];
964
+ if ( TYPE(content) != T_STRING)
965
+ content=rb_obj_as_string(content);
966
+
967
+ case 1:
968
+ name=check_string_or_symbol( argv[0] );
969
+ return ruby_xml_node_new_string(class,Qnil,name,content);
970
+
971
+ default:
972
+ rb_raise(rb_eArgError, "wrong number of arguments (1 or 2) given %d",argc);
973
+ }
974
+ }
975
+
976
+ /*
977
+ * call-seq:
978
+ * node.next -> XML::Node
979
+ *
980
+ * Obtain the next sibling node, if any.
981
+ */
982
+ VALUE
983
+ ruby_xml_node_next_get(VALUE self) {
984
+ xmlNodePtr xnode;
985
+
986
+ Data_Get_Struct(self, xmlNode, xnode);
987
+
988
+ if (xnode->next)
989
+ return(ruby_xml_node2_wrap(cXMLNode, xnode->next));
990
+ else
991
+ return(Qnil);
992
+ }
993
+
994
+
995
+ /*
996
+ * call-seq:
997
+ * node.next = node
998
+ *
999
+ * Insert the specified node as this node's next sibling.
1000
+ */
1001
+ VALUE
1002
+ ruby_xml_node_next_set(VALUE self, VALUE rnode) {
1003
+ xmlNodePtr cnode, pnode, ret;
1004
+
1005
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1006
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1007
+
1008
+ Data_Get_Struct(self, xmlNode, pnode);
1009
+ Data_Get_Struct(rnode, xmlNode, cnode);
1010
+
1011
+ ret = xmlAddNextSibling(pnode, cnode);
1012
+ if (ret == NULL)
1013
+ ruby_xml_raise(&xmlLastError);
1014
+
1015
+ return(ruby_xml_node2_wrap(cXMLNode, ret));
1016
+ }
1017
+
1018
+
1019
+ /*
1020
+ * call-seq:
1021
+ * node.ns? -> (true|false)
1022
+ *
1023
+ * Determine whether this node has a namespace.
1024
+ */
1025
+ VALUE
1026
+ ruby_xml_node_ns_q(VALUE self) {
1027
+ xmlNodePtr xnode;
1028
+ Data_Get_Struct(self, xmlNode, xnode);
1029
+ if (xnode->ns == NULL)
1030
+ return(Qfalse);
1031
+ else
1032
+ return(Qtrue);
1033
+ }
1034
+
1035
+ /*
1036
+ * call-seq:
1037
+ * node.ns_def? -> (true|false)
1038
+ *
1039
+ * Obtain an array of +XML::NS+ objects representing
1040
+ * this node's xmlns attributes
1041
+ */
1042
+ VALUE
1043
+ ruby_xml_node_ns_def_q(VALUE self) {
1044
+ xmlNodePtr xnode;
1045
+ Data_Get_Struct(self, xmlNode, xnode);
1046
+ if (xnode->nsDef == NULL)
1047
+ return(Qfalse);
1048
+ else
1049
+ return(Qtrue);
1050
+ }
1051
+
1052
+
1053
+ /*
1054
+ * call-seq:
1055
+ * node.ns_def -> namespace
1056
+ *
1057
+ * Obtain this node's default namespace.
1058
+ */
1059
+ VALUE
1060
+ ruby_xml_node_ns_def_get(VALUE self) {
1061
+ xmlNodePtr xnode;
1062
+ Data_Get_Struct(self, xmlNode, xnode);
1063
+ if (xnode->nsDef == NULL)
1064
+ return(Qnil);
1065
+ else
1066
+ return(ruby_xml_ns_wrap(xnode->nsDef));
1067
+ }
1068
+
1069
+
1070
+ /*
1071
+ * call-seq:
1072
+ * node.parent -> XML::Node
1073
+ *
1074
+ * Obtain this node's parent node, if any.
1075
+ */
1076
+ VALUE
1077
+ ruby_xml_node_parent_get(VALUE self) {
1078
+ xmlNodePtr xnode;
1079
+
1080
+ Data_Get_Struct(self, xmlNode, xnode);
1081
+
1082
+ if (xnode->parent)
1083
+ return(ruby_xml_node2_wrap(cXMLNode, xnode->parent));
1084
+ else
1085
+ return(Qnil);
1086
+ }
1087
+
1088
+
1089
+ /*
1090
+ * call-seq:
1091
+ * node.path -> path
1092
+ *
1093
+ * Obtain this node's path.
1094
+ */
1095
+ VALUE
1096
+ ruby_xml_node_path(VALUE self) {
1097
+ xmlNodePtr xnode;
1098
+ xmlChar *path;
1099
+
1100
+ Data_Get_Struct(self, xmlNode, xnode);
1101
+ path = xmlGetNodePath(xnode);
1102
+
1103
+ if (path == NULL)
1104
+ return(Qnil);
1105
+ else
1106
+ return(rb_str_new2((const char*)path));
1107
+ }
1108
+
1109
+
1110
+ /*
1111
+ * call-seq:
1112
+ * node.pointer -> XML::NodeSet
1113
+ *
1114
+ * Evaluates an XPointer expression relative to this node.
1115
+ */
1116
+ VALUE
1117
+ ruby_xml_node_pointer(VALUE self, VALUE xptr_str) {
1118
+ return(ruby_xml_xpointer_point2(self, xptr_str));
1119
+ }
1120
+
1121
+
1122
+ /*
1123
+ * call-seq:
1124
+ * node.prev -> XML::Node
1125
+ *
1126
+ * Obtain the previous sibling, if any.
1127
+ */
1128
+ VALUE
1129
+ ruby_xml_node_prev_get(VALUE self) {
1130
+ xmlNodePtr xnode;
1131
+ xmlNodePtr node;
1132
+ Data_Get_Struct(self, xmlNode, xnode);
1133
+
1134
+ switch (xnode->type) {
1135
+ case XML_DOCUMENT_NODE:
1136
+ #ifdef LIBXML_DOCB_ENABLED
1137
+ case XML_DOCB_DOCUMENT_NODE:
1138
+ #endif
1139
+ case XML_HTML_DOCUMENT_NODE:
1140
+ case XML_NAMESPACE_DECL:
1141
+ node = NULL;
1142
+ break;
1143
+ case XML_ATTRIBUTE_NODE:
1144
+ {
1145
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
1146
+ node = (xmlNodePtr) attr->prev;
1147
+ }
1148
+ break;
1149
+ default:
1150
+ node = xnode->prev;
1151
+ break;
1152
+ }
1153
+
1154
+ if (node == NULL)
1155
+ return(Qnil);
1156
+ else
1157
+ return(ruby_xml_node2_wrap(cXMLNode, node));
1158
+ }
1159
+
1160
+
1161
+ /*
1162
+ * call-seq:
1163
+ * node.prev = node
1164
+ *
1165
+ * Insert the specified node as this node's previous sibling.
1166
+ */
1167
+ VALUE
1168
+ ruby_xml_node_prev_set(VALUE self, VALUE rnode) {
1169
+ xmlNodePtr cnode, pnode, ret;
1170
+
1171
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1172
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1173
+
1174
+ Data_Get_Struct(self, xmlNode, pnode);
1175
+ Data_Get_Struct(rnode, xmlNode, cnode);
1176
+
1177
+ ret = xmlAddPrevSibling(pnode, cnode);
1178
+ if (ret == NULL)
1179
+ ruby_xml_raise(&xmlLastError);
1180
+
1181
+ return(ruby_xml_node2_wrap(cXMLNode, ret));
1182
+ }
1183
+
1184
+ /*
1185
+ * call-seq:
1186
+ * node.attributes -> attributes
1187
+ *
1188
+ * Returns the XML::Attributes for this node.
1189
+ */
1190
+ VALUE
1191
+ ruby_xml_node_attributes_get(VALUE self) {
1192
+ xmlNodePtr xnode;
1193
+
1194
+ Data_Get_Struct(self, xmlNode, xnode);
1195
+ return ruby_xml_attributes_new(xnode);
1196
+ }
1197
+
1198
+ /*
1199
+ * call-seq:
1200
+ * node.property("name") -> "string"
1201
+ * node["name"] -> "string"
1202
+ *
1203
+ * Obtain the named pyroperty.
1204
+ */
1205
+ VALUE
1206
+ ruby_xml_node_attribute_get(VALUE self, VALUE name) {
1207
+ VALUE attributes = ruby_xml_node_attributes_get(self);
1208
+ return ruby_xml_attributes_attribute_get(attributes, name);
1209
+ }
1210
+
1211
+ /*
1212
+ * call-seq:
1213
+ * node["name"] = "string"
1214
+ *
1215
+ * Set the named property.
1216
+ */
1217
+ VALUE
1218
+ ruby_xml_node_property_set(VALUE self, VALUE name, VALUE value) {
1219
+ VALUE attributes = ruby_xml_node_attributes_get(self);
1220
+ return ruby_xml_attributes_attribute_set(attributes, name, value);
1221
+ }
1222
+
1223
+
1224
+ /*
1225
+ * call-seq:
1226
+ * node.remove! -> nil
1227
+ *
1228
+ * Removes this node from it's parent.
1229
+ */
1230
+ VALUE
1231
+ ruby_xml_node_remove_ex(VALUE self) {
1232
+ xmlNodePtr xnode;
1233
+ Data_Get_Struct(self, xmlNode, xnode);
1234
+ xmlUnlinkNode(xnode);
1235
+ return(Qnil);
1236
+ }
1237
+
1238
+
1239
+ /*
1240
+ * call-seq:
1241
+ * node.search_href -> namespace
1242
+ *
1243
+ * Search for a namespace by href.
1244
+ */
1245
+ VALUE
1246
+ ruby_xml_node_search_href(VALUE self, VALUE href) {
1247
+ xmlNodePtr xnode;
1248
+
1249
+ Check_Type(href, T_STRING);
1250
+ Data_Get_Struct(self, xmlNode, xnode);
1251
+ return(ruby_xml_ns_wrap(xmlSearchNsByHref(xnode->doc, xnode,
1252
+ (xmlChar*)StringValuePtr(href))));
1253
+ }
1254
+
1255
+
1256
+ /*
1257
+ * call-seq:
1258
+ * node.search_ns -> namespace
1259
+ *
1260
+ * Search for a namespace by namespace.
1261
+ */
1262
+ VALUE
1263
+ ruby_xml_node_search_ns(VALUE self, VALUE ns) {
1264
+ xmlNodePtr xnode;
1265
+
1266
+ Check_Type(ns, T_STRING);
1267
+ Data_Get_Struct(self, xmlNode, xnode);
1268
+ return(ruby_xml_ns_wrap(xmlSearchNs(xnode->doc, xnode,
1269
+ (xmlChar*)StringValuePtr(ns))));
1270
+ }
1271
+
1272
+
1273
+ /*
1274
+ * call-seq:
1275
+ * node.sibling(node) -> XML::Node
1276
+ *
1277
+ * Add the specified node as a sibling of this node.
1278
+ */
1279
+ VALUE
1280
+ ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
1281
+ xmlNodePtr cnode, pnode, ret;
1282
+ VALUE obj;
1283
+
1284
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1285
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1286
+
1287
+ Data_Get_Struct(self, xmlNode, pnode);
1288
+ Data_Get_Struct(rnode, xmlNode, cnode);
1289
+
1290
+ ret = xmlAddSibling(pnode, cnode);
1291
+ if (ret == NULL)
1292
+ ruby_xml_raise(&xmlLastError);
1293
+
1294
+ if (ret->_private==NULL)
1295
+ obj=ruby_xml_node2_wrap(cXMLNode,ret);
1296
+ else
1297
+ obj=(VALUE)ret->_private;
1298
+
1299
+ return obj;
1300
+ }
1301
+
1302
+
1303
+ /*
1304
+ * call-seq:
1305
+ * node.space_preserve -> (true|false)
1306
+ *
1307
+ * Determine whether this node preserves whitespace.
1308
+ */
1309
+ VALUE
1310
+ ruby_xml_node_space_preserve_get(VALUE self) {
1311
+ xmlNodePtr xnode;
1312
+
1313
+ Data_Get_Struct(self, xmlNode, xnode);
1314
+ return(INT2NUM(xmlNodeGetSpacePreserve(xnode)));
1315
+ }
1316
+
1317
+
1318
+ /*
1319
+ * call-seq:
1320
+ * node.space_preserve = true|false
1321
+ *
1322
+ * Control whether this node preserves whitespace.
1323
+ */
1324
+ VALUE
1325
+ ruby_xml_node_space_preserve_set(VALUE self, VALUE bool) {
1326
+ xmlNodePtr xnode;
1327
+ Data_Get_Struct(self, xmlNode, xnode);
1328
+
1329
+ if (TYPE(bool) == T_FALSE)
1330
+ xmlNodeSetSpacePreserve(xnode, 1);
1331
+ else
1332
+ xmlNodeSetSpacePreserve(xnode, 0);
1333
+
1334
+ return(Qnil);
1335
+ }
1336
+
1337
+ /*
1338
+ * call-seq:
1339
+ * node.to_s -> "string"
1340
+ *
1341
+ * Coerce this node to a string representation of
1342
+ * it's XML.
1343
+ */
1344
+ VALUE
1345
+ ruby_xml_node_to_s(VALUE self) {
1346
+ xmlNodePtr xnode;
1347
+ xmlBufferPtr buf;
1348
+ VALUE result;
1349
+
1350
+ Data_Get_Struct(self, xmlNode, xnode);
1351
+ buf = xmlBufferCreate();
1352
+ xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
1353
+ result = rb_str_new2((const char*)buf->content);
1354
+
1355
+ xmlBufferFree(buf);
1356
+ return result;
1357
+ }
1358
+
1359
+
1360
+ /*
1361
+ * call-seq:
1362
+ * node.type -> num
1363
+ *
1364
+ * Obtain this node's type identifier.
1365
+ */
1366
+ VALUE
1367
+ ruby_xml_node_type(VALUE self) {
1368
+ xmlNodePtr xnode;
1369
+ Data_Get_Struct(self, xmlNode, xnode);
1370
+ return(INT2NUM(xnode->type));
1371
+ }
1372
+
1373
+
1374
+
1375
+
1376
+ /*
1377
+ * call-seq:
1378
+ * node.copy -> XML::Node
1379
+ *
1380
+ * Creates a copy of this node. To create a
1381
+ * shallow copy set the deep parameter to false.
1382
+ * To create a deep copy set the deep parameter
1383
+ * to true.
1384
+ *
1385
+ */
1386
+ VALUE
1387
+ ruby_xml_node_copy(VALUE self, VALUE deep) {
1388
+ xmlNodePtr xnode;
1389
+ xmlNodePtr xcopy;
1390
+ int recursive = (deep==Qnil || deep==Qfalse) ? 0 : 1;
1391
+ Data_Get_Struct(self, xmlNode, xnode);
1392
+
1393
+ xcopy = xmlCopyNode(xnode, recursive);
1394
+
1395
+ if (xcopy)
1396
+ return ruby_xml_node2_wrap(cXMLNode, xcopy);
1397
+ else
1398
+ return Qnil;
1399
+ }
1400
+
1401
+ /*
1402
+ * call-seq:
1403
+ * XML::Node.new_text(content = nil) -> XML::Node
1404
+ *
1405
+ * Create a new text node, optionally setting
1406
+ * the node's content.
1407
+ *
1408
+ */
1409
+ VALUE
1410
+ ruby_xml_node_new_text(VALUE class, VALUE text)
1411
+ {
1412
+ VALUE obj;
1413
+ xmlNodePtr xnode;
1414
+
1415
+ if ( NIL_P(text) )
1416
+ return Qnil;
1417
+
1418
+ if (TYPE(text) != T_STRING )
1419
+ rb_raise(rb_eTypeError, "requires string argument");
1420
+
1421
+ xnode=xmlNewText((xmlChar*)STR2CSTR(text));
1422
+ if ( xnode == NULL )
1423
+ return Qnil;
1424
+
1425
+ obj=ruby_xml_node2_wrap(class,xnode);
1426
+ rb_obj_call_init(obj,0,NULL);
1427
+ return obj;
1428
+ }
1429
+
1430
+ void
1431
+ ruby_xml_node_registerNode(xmlNodePtr node)
1432
+ {
1433
+ node->_private=NULL;
1434
+ }
1435
+
1436
+ void
1437
+ ruby_xml_node_deregisterNode(xmlNodePtr xnode)
1438
+ {
1439
+ VALUE node;
1440
+
1441
+ if (xnode->_private==NULL ) return;
1442
+ node = (VALUE)xnode->_private;
1443
+ DATA_PTR(node) = NULL;
1444
+ }
1445
+
1446
+ // Rdoc needs to know
1447
+ #ifdef RDOC_NEVER_DEFINED
1448
+ mLibXML = rb_define_module("LibXML");
1449
+ mXML = rb_define_module_under(mLibXML, "XML");
1450
+ #endif
1451
+
1452
+ void
1453
+ ruby_init_xml_node(void) {
1454
+ xmlRegisterNodeDefault(ruby_xml_node_registerNode);
1455
+ xmlDeregisterNodeDefault(ruby_xml_node_deregisterNode);
1456
+
1457
+ cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
1458
+
1459
+ rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
1460
+ rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
1461
+ rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
1462
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
1463
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
1464
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
1465
+ rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
1466
+ rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
1467
+ rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
1468
+ rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
1469
+ rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
1470
+ rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
1471
+ rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
1472
+ rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
1473
+
1474
+ rb_define_const(cXMLNode, "ELEMENT_NODE", INT2FIX(XML_ELEMENT_NODE));
1475
+ rb_define_const(cXMLNode, "ATTRIBUTE_NODE", INT2FIX(XML_ATTRIBUTE_NODE));
1476
+ rb_define_const(cXMLNode, "TEXT_NODE", INT2FIX(XML_TEXT_NODE));
1477
+ rb_define_const(cXMLNode, "CDATA_SECTION_NODE", INT2FIX(XML_CDATA_SECTION_NODE));
1478
+ rb_define_const(cXMLNode, "ENTITY_REF_NODE", INT2FIX(XML_ENTITY_REF_NODE));
1479
+ rb_define_const(cXMLNode, "ENTITY_NODE", INT2FIX(XML_ENTITY_NODE));
1480
+ rb_define_const(cXMLNode, "PI_NODE", INT2FIX(XML_PI_NODE));
1481
+ rb_define_const(cXMLNode, "COMMENT_NODE", INT2FIX(XML_COMMENT_NODE));
1482
+ rb_define_const(cXMLNode, "DOCUMENT_NODE", INT2FIX(XML_DOCUMENT_NODE));
1483
+ rb_define_const(cXMLNode, "DOCUMENT_TYPE_NODE", INT2FIX(XML_DOCUMENT_TYPE_NODE));
1484
+ rb_define_const(cXMLNode, "DOCUMENT_FRAG_NODE", INT2FIX(XML_DOCUMENT_FRAG_NODE));
1485
+ rb_define_const(cXMLNode, "NOTATION_NODE", INT2FIX(XML_NOTATION_NODE));
1486
+ rb_define_const(cXMLNode, "HTML_DOCUMENT_NODE", INT2FIX(XML_HTML_DOCUMENT_NODE));
1487
+ rb_define_const(cXMLNode, "DTD_NODE", INT2FIX(XML_DTD_NODE));
1488
+ rb_define_const(cXMLNode, "ELEMENT_DECL", INT2FIX(XML_ELEMENT_DECL));
1489
+ rb_define_const(cXMLNode, "ATTRIBUTE_DECL", INT2FIX(XML_ATTRIBUTE_DECL));
1490
+ rb_define_const(cXMLNode, "ENTITY_DECL", INT2FIX(XML_ENTITY_DECL));
1491
+ rb_define_const(cXMLNode, "NAMESPACE_DECL", INT2FIX(XML_NAMESPACE_DECL));
1492
+ rb_define_const(cXMLNode, "XINCLUDE_START", INT2FIX(XML_XINCLUDE_START));
1493
+ rb_define_const(cXMLNode, "XINCLUDE_END", INT2FIX(XML_XINCLUDE_END));
1494
+
1495
+ #ifdef LIBXML_DOCB_ENABLED
1496
+ rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", INT2FIX(XML_DOCB_DOCUMENT_NODE));
1497
+ #else
1498
+ rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", Qnil);
1499
+ #endif
1500
+
1501
+ rb_define_singleton_method(cXMLNode, "new", ruby_xml_node_new_string_bc, -1);
1502
+ rb_define_singleton_method(cXMLNode, "new_cdata", ruby_xml_node_new_cdata, -1);
1503
+ rb_define_singleton_method(cXMLNode, "new_comment", ruby_xml_node_new_comment, -1);
1504
+ rb_define_singleton_method(cXMLNode, "new_text", ruby_xml_node_new_text, 1);
1505
+
1506
+ /* Traversal */
1507
+ rb_include_module(cXMLNode, rb_mEnumerable);
1508
+ rb_define_method(cXMLNode, "[]", ruby_xml_node_attribute_get, 1);
1509
+ rb_define_method(cXMLNode, "each", ruby_xml_node_each, 0);
1510
+ rb_define_method(cXMLNode, "first", ruby_xml_node_first_get, 0);
1511
+ rb_define_method(cXMLNode, "last", ruby_xml_node_last_get, 0);
1512
+ rb_define_method(cXMLNode, "next", ruby_xml_node_next_get, 0);
1513
+ rb_define_method(cXMLNode, "parent", ruby_xml_node_parent_get, 0);
1514
+ rb_define_method(cXMLNode, "prev", ruby_xml_node_prev_get, 0);
1515
+
1516
+ /* Modification */
1517
+ rb_define_method(cXMLNode, "<<", ruby_xml_node_content_add, 1);
1518
+ rb_define_method(cXMLNode, "[]=", ruby_xml_node_property_set, 2);
1519
+ rb_define_method(cXMLNode, "child_add", ruby_xml_node_child_add, 1);
1520
+ rb_define_method(cXMLNode, "child=", ruby_xml_node_child_set, 1);
1521
+ rb_define_method(cXMLNode, "sibling=", ruby_xml_node_sibling_set, 1);
1522
+ rb_define_method(cXMLNode, "next=", ruby_xml_node_next_set, 1);
1523
+ rb_define_method(cXMLNode, "prev=", ruby_xml_node_prev_set, 1);
1524
+
1525
+
1526
+ /* Rest of the node api */
1527
+ rb_define_method(cXMLNode, "attributes", ruby_xml_node_attributes_get, 0);
1528
+ rb_define_method(cXMLNode, "base", ruby_xml_node_base_get, 0);
1529
+ rb_define_method(cXMLNode, "base=", ruby_xml_node_base_set, 1);
1530
+ rb_define_method(cXMLNode, "blank?", ruby_xml_node_empty_q, 0);
1531
+ rb_define_method(cXMLNode, "copy", ruby_xml_node_copy, 1);
1532
+ rb_define_method(cXMLNode, "content", ruby_xml_node_content_get, 0);
1533
+ rb_define_method(cXMLNode, "content=", ruby_xml_node_content_set, 1);
1534
+ rb_define_method(cXMLNode, "content_stripped", ruby_xml_node_content_stripped_get, 0);
1535
+ rb_define_method(cXMLNode, "doc", ruby_xml_node_doc, 0);
1536
+ rb_define_method(cXMLNode, "dump", ruby_xml_node_dump, 0);
1537
+ rb_define_method(cXMLNode, "debug_dump", ruby_xml_node_debug_dump, 0);
1538
+ rb_define_method(cXMLNode, "empty?", ruby_xml_node_empty_q, 0);
1539
+ rb_define_method(cXMLNode, "eql?", ruby_xml_node_eql_q, 1);
1540
+ rb_define_method(cXMLNode, "lang", ruby_xml_node_lang_get, 0);
1541
+ rb_define_method(cXMLNode, "lang=", ruby_xml_node_lang_set, 1);
1542
+ rb_define_method(cXMLNode, "line_num", ruby_xml_node_line_num, 0);
1543
+ rb_define_method(cXMLNode, "name", ruby_xml_node_name_get, 0);
1544
+ rb_define_method(cXMLNode, "name=", ruby_xml_node_name_set, 1);
1545
+ rb_define_method(cXMLNode, "namespace", ruby_xml_node_namespace_get, 0);
1546
+ rb_define_method(cXMLNode, "namespace_node", ruby_xml_node_namespace_get_node, 0);
1547
+ rb_define_method(cXMLNode, "namespace=", ruby_xml_node_namespace_set, -1);
1548
+ rb_define_method(cXMLNode, "node_type", ruby_xml_node_type, 0);
1549
+ rb_define_method(cXMLNode, "ns", ruby_xml_node_namespace_get, 0);
1550
+ rb_define_method(cXMLNode, "ns?", ruby_xml_node_ns_q, 0);
1551
+ rb_define_method(cXMLNode, "ns_def?", ruby_xml_node_ns_def_q, 0);
1552
+ rb_define_method(cXMLNode, "ns_def", ruby_xml_node_ns_def_get, 0);
1553
+ rb_define_method(cXMLNode, "path", ruby_xml_node_path, 0);
1554
+ rb_define_method(cXMLNode, "pointer", ruby_xml_node_pointer, 1);
1555
+ rb_define_method(cXMLNode, "remove!", ruby_xml_node_remove_ex, 0);
1556
+ rb_define_method(cXMLNode, "search_ns", ruby_xml_node_search_ns, 1);
1557
+ rb_define_method(cXMLNode, "search_href", ruby_xml_node_search_href, 1);
1558
+ rb_define_method(cXMLNode, "space_preserve", ruby_xml_node_space_preserve_get, 0);
1559
+ rb_define_method(cXMLNode, "space_preserve=", ruby_xml_node_space_preserve_set, 1);
1560
+ rb_define_method(cXMLNode, "to_s", ruby_xml_node_to_s, 0);
1561
+ rb_define_method(cXMLNode, "xlink?", ruby_xml_node_xlink_q, 0);
1562
+ rb_define_method(cXMLNode, "xlink_type", ruby_xml_node_xlink_type, 0);
1563
+ rb_define_method(cXMLNode, "xlink_type_name", ruby_xml_node_xlink_type_name, 0);
1564
+
1565
+ rb_define_alias(cXMLNode, "==", "eql?");
1566
+ }