libxml-ruby 2.9.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY +790 -0
  3. data/LICENSE +21 -0
  4. data/MANIFEST +166 -0
  5. data/README.rdoc +184 -0
  6. data/Rakefile +81 -0
  7. data/ext/libxml/extconf.h +4 -0
  8. data/ext/libxml/extconf.rb +57 -0
  9. data/ext/libxml/libxml.c +80 -0
  10. data/ext/libxml/libxml_ruby.def +35 -0
  11. data/ext/libxml/ruby_libxml.h +75 -0
  12. data/ext/libxml/ruby_xml.c +977 -0
  13. data/ext/libxml/ruby_xml.h +20 -0
  14. data/ext/libxml/ruby_xml_attr.c +333 -0
  15. data/ext/libxml/ruby_xml_attr.h +12 -0
  16. data/ext/libxml/ruby_xml_attr_decl.c +153 -0
  17. data/ext/libxml/ruby_xml_attr_decl.h +11 -0
  18. data/ext/libxml/ruby_xml_attributes.c +275 -0
  19. data/ext/libxml/ruby_xml_attributes.h +15 -0
  20. data/ext/libxml/ruby_xml_cbg.c +85 -0
  21. data/ext/libxml/ruby_xml_document.c +1133 -0
  22. data/ext/libxml/ruby_xml_document.h +11 -0
  23. data/ext/libxml/ruby_xml_dtd.c +261 -0
  24. data/ext/libxml/ruby_xml_dtd.h +9 -0
  25. data/ext/libxml/ruby_xml_encoding.c +262 -0
  26. data/ext/libxml/ruby_xml_encoding.h +19 -0
  27. data/ext/libxml/ruby_xml_error.c +996 -0
  28. data/ext/libxml/ruby_xml_error.h +12 -0
  29. data/ext/libxml/ruby_xml_html_parser.c +92 -0
  30. data/ext/libxml/ruby_xml_html_parser.h +10 -0
  31. data/ext/libxml/ruby_xml_html_parser_context.c +337 -0
  32. data/ext/libxml/ruby_xml_html_parser_context.h +10 -0
  33. data/ext/libxml/ruby_xml_html_parser_options.c +46 -0
  34. data/ext/libxml/ruby_xml_html_parser_options.h +10 -0
  35. data/ext/libxml/ruby_xml_input_cbg.c +191 -0
  36. data/ext/libxml/ruby_xml_input_cbg.h +20 -0
  37. data/ext/libxml/ruby_xml_io.c +52 -0
  38. data/ext/libxml/ruby_xml_io.h +10 -0
  39. data/ext/libxml/ruby_xml_namespace.c +153 -0
  40. data/ext/libxml/ruby_xml_namespace.h +10 -0
  41. data/ext/libxml/ruby_xml_namespaces.c +293 -0
  42. data/ext/libxml/ruby_xml_namespaces.h +9 -0
  43. data/ext/libxml/ruby_xml_node.c +1446 -0
  44. data/ext/libxml/ruby_xml_node.h +11 -0
  45. data/ext/libxml/ruby_xml_parser.c +94 -0
  46. data/ext/libxml/ruby_xml_parser.h +12 -0
  47. data/ext/libxml/ruby_xml_parser_context.c +999 -0
  48. data/ext/libxml/ruby_xml_parser_context.h +10 -0
  49. data/ext/libxml/ruby_xml_parser_options.c +66 -0
  50. data/ext/libxml/ruby_xml_parser_options.h +12 -0
  51. data/ext/libxml/ruby_xml_reader.c +1226 -0
  52. data/ext/libxml/ruby_xml_reader.h +17 -0
  53. data/ext/libxml/ruby_xml_relaxng.c +110 -0
  54. data/ext/libxml/ruby_xml_relaxng.h +10 -0
  55. data/ext/libxml/ruby_xml_sax2_handler.c +326 -0
  56. data/ext/libxml/ruby_xml_sax2_handler.h +10 -0
  57. data/ext/libxml/ruby_xml_sax_parser.c +120 -0
  58. data/ext/libxml/ruby_xml_sax_parser.h +10 -0
  59. data/ext/libxml/ruby_xml_schema.c +300 -0
  60. data/ext/libxml/ruby_xml_schema.h +809 -0
  61. data/ext/libxml/ruby_xml_schema_attribute.c +109 -0
  62. data/ext/libxml/ruby_xml_schema_attribute.h +15 -0
  63. data/ext/libxml/ruby_xml_schema_element.c +94 -0
  64. data/ext/libxml/ruby_xml_schema_element.h +14 -0
  65. data/ext/libxml/ruby_xml_schema_facet.c +52 -0
  66. data/ext/libxml/ruby_xml_schema_facet.h +13 -0
  67. data/ext/libxml/ruby_xml_schema_type.c +259 -0
  68. data/ext/libxml/ruby_xml_schema_type.h +9 -0
  69. data/ext/libxml/ruby_xml_version.h +9 -0
  70. data/ext/libxml/ruby_xml_writer.c +1136 -0
  71. data/ext/libxml/ruby_xml_writer.h +10 -0
  72. data/ext/libxml/ruby_xml_xinclude.c +16 -0
  73. data/ext/libxml/ruby_xml_xinclude.h +11 -0
  74. data/ext/libxml/ruby_xml_xpath.c +188 -0
  75. data/ext/libxml/ruby_xml_xpath.h +13 -0
  76. data/ext/libxml/ruby_xml_xpath_context.c +360 -0
  77. data/ext/libxml/ruby_xml_xpath_context.h +9 -0
  78. data/ext/libxml/ruby_xml_xpath_expression.c +81 -0
  79. data/ext/libxml/ruby_xml_xpath_expression.h +10 -0
  80. data/ext/libxml/ruby_xml_xpath_object.c +335 -0
  81. data/ext/libxml/ruby_xml_xpath_object.h +17 -0
  82. data/ext/libxml/ruby_xml_xpointer.c +99 -0
  83. data/ext/libxml/ruby_xml_xpointer.h +11 -0
  84. data/ext/vc/libxml_ruby.sln +26 -0
  85. data/lib/2.3/libxml_ruby.so +0 -0
  86. data/lib/libs/libiconv-2.dll +0 -0
  87. data/lib/libs/libxml2-2.dll +0 -0
  88. data/lib/libs/zlib1.dll +0 -0
  89. data/lib/libxml.rb +35 -0
  90. data/lib/libxml/attr.rb +123 -0
  91. data/lib/libxml/attr_decl.rb +80 -0
  92. data/lib/libxml/attributes.rb +14 -0
  93. data/lib/libxml/document.rb +194 -0
  94. data/lib/libxml/error.rb +95 -0
  95. data/lib/libxml/hpricot.rb +78 -0
  96. data/lib/libxml/html_parser.rb +96 -0
  97. data/lib/libxml/namespace.rb +62 -0
  98. data/lib/libxml/namespaces.rb +38 -0
  99. data/lib/libxml/node.rb +399 -0
  100. data/lib/libxml/ns.rb +22 -0
  101. data/lib/libxml/parser.rb +367 -0
  102. data/lib/libxml/properties.rb +23 -0
  103. data/lib/libxml/reader.rb +29 -0
  104. data/lib/libxml/sax_callbacks.rb +180 -0
  105. data/lib/libxml/sax_parser.rb +58 -0
  106. data/lib/libxml/schema.rb +67 -0
  107. data/lib/libxml/schema/attribute.rb +19 -0
  108. data/lib/libxml/schema/element.rb +27 -0
  109. data/lib/libxml/schema/type.rb +29 -0
  110. data/lib/libxml/tree.rb +29 -0
  111. data/lib/libxml/xpath_object.rb +16 -0
  112. data/lib/xml.rb +14 -0
  113. data/lib/xml/libxml.rb +10 -0
  114. data/libxml-ruby.gemspec +47 -0
  115. data/script/benchmark/depixelate +634 -0
  116. data/script/benchmark/hamlet.xml +9055 -0
  117. data/script/benchmark/parsecount +170 -0
  118. data/script/benchmark/sock_entries.xml +507 -0
  119. data/script/benchmark/throughput +41 -0
  120. data/script/test +6 -0
  121. data/setup.rb +1585 -0
  122. data/test/c14n/given/doc.dtd +1 -0
  123. data/test/c14n/given/example-1.xml +14 -0
  124. data/test/c14n/given/example-2.xml +11 -0
  125. data/test/c14n/given/example-3.xml +18 -0
  126. data/test/c14n/given/example-4.xml +9 -0
  127. data/test/c14n/given/example-5.xml +12 -0
  128. data/test/c14n/given/example-6.xml +2 -0
  129. data/test/c14n/given/example-7.xml +11 -0
  130. data/test/c14n/given/example-8.xml +11 -0
  131. data/test/c14n/given/example-8.xpath +10 -0
  132. data/test/c14n/given/world.txt +1 -0
  133. data/test/c14n/result/1-1-without-comments/example-1 +4 -0
  134. data/test/c14n/result/1-1-without-comments/example-2 +11 -0
  135. data/test/c14n/result/1-1-without-comments/example-3 +14 -0
  136. data/test/c14n/result/1-1-without-comments/example-4 +9 -0
  137. data/test/c14n/result/1-1-without-comments/example-5 +3 -0
  138. data/test/c14n/result/1-1-without-comments/example-6 +1 -0
  139. data/test/c14n/result/1-1-without-comments/example-7 +1 -0
  140. data/test/c14n/result/1-1-without-comments/example-8 +1 -0
  141. data/test/c14n/result/with-comments/example-1 +6 -0
  142. data/test/c14n/result/with-comments/example-2 +11 -0
  143. data/test/c14n/result/with-comments/example-3 +14 -0
  144. data/test/c14n/result/with-comments/example-4 +9 -0
  145. data/test/c14n/result/with-comments/example-5 +4 -0
  146. data/test/c14n/result/with-comments/example-6 +1 -0
  147. data/test/c14n/result/with-comments/example-7 +1 -0
  148. data/test/c14n/result/without-comments/example-1 +4 -0
  149. data/test/c14n/result/without-comments/example-2 +11 -0
  150. data/test/c14n/result/without-comments/example-3 +14 -0
  151. data/test/c14n/result/without-comments/example-4 +9 -0
  152. data/test/c14n/result/without-comments/example-5 +3 -0
  153. data/test/c14n/result/without-comments/example-6 +1 -0
  154. data/test/c14n/result/without-comments/example-7 +1 -0
  155. data/test/model/atom.xml +13 -0
  156. data/test/model/bands.iso-8859-1.xml +5 -0
  157. data/test/model/bands.utf-8.xml +5 -0
  158. data/test/model/bands.xml +5 -0
  159. data/test/model/books.xml +154 -0
  160. data/test/model/merge_bug_data.xml +58 -0
  161. data/test/model/ruby-lang.html +238 -0
  162. data/test/model/rubynet.xml +79 -0
  163. data/test/model/rubynet_project +1 -0
  164. data/test/model/shiporder.rnc +28 -0
  165. data/test/model/shiporder.rng +86 -0
  166. data/test/model/shiporder.xml +23 -0
  167. data/test/model/shiporder.xsd +40 -0
  168. data/test/model/soap.xml +27 -0
  169. data/test/model/xinclude.xml +5 -0
  170. data/test/tc_attr.rb +181 -0
  171. data/test/tc_attr_decl.rb +132 -0
  172. data/test/tc_attributes.rb +142 -0
  173. data/test/tc_canonicalize.rb +124 -0
  174. data/test/tc_deprecated_require.rb +12 -0
  175. data/test/tc_document.rb +125 -0
  176. data/test/tc_document_write.rb +195 -0
  177. data/test/tc_dtd.rb +128 -0
  178. data/test/tc_encoding.rb +126 -0
  179. data/test/tc_encoding_sax.rb +115 -0
  180. data/test/tc_error.rb +179 -0
  181. data/test/tc_html_parser.rb +161 -0
  182. data/test/tc_html_parser_context.rb +23 -0
  183. data/test/tc_namespace.rb +61 -0
  184. data/test/tc_namespaces.rb +209 -0
  185. data/test/tc_node.rb +215 -0
  186. data/test/tc_node_cdata.rb +50 -0
  187. data/test/tc_node_comment.rb +32 -0
  188. data/test/tc_node_copy.rb +41 -0
  189. data/test/tc_node_edit.rb +174 -0
  190. data/test/tc_node_pi.rb +39 -0
  191. data/test/tc_node_text.rb +70 -0
  192. data/test/tc_node_write.rb +107 -0
  193. data/test/tc_node_xlink.rb +28 -0
  194. data/test/tc_parser.rb +375 -0
  195. data/test/tc_parser_context.rb +204 -0
  196. data/test/tc_properties.rb +38 -0
  197. data/test/tc_reader.rb +399 -0
  198. data/test/tc_relaxng.rb +53 -0
  199. data/test/tc_sax_parser.rb +319 -0
  200. data/test/tc_schema.rb +161 -0
  201. data/test/tc_traversal.rb +152 -0
  202. data/test/tc_writer.rb +447 -0
  203. data/test/tc_xinclude.rb +20 -0
  204. data/test/tc_xml.rb +225 -0
  205. data/test/tc_xpath.rb +244 -0
  206. data/test/tc_xpath_context.rb +88 -0
  207. data/test/tc_xpath_expression.rb +37 -0
  208. data/test/tc_xpointer.rb +72 -0
  209. data/test/test_helper.rb +16 -0
  210. data/test/test_suite.rb +49 -0
  211. metadata +344 -0
@@ -0,0 +1,11 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_ATTR_DECL__
4
+ #define __RXML_ATTR_DECL__
5
+
6
+ extern VALUE cXMLAttrDecl;
7
+
8
+ void rxml_init_attr_decl(void);
9
+ VALUE rxml_attr_decl_wrap(xmlAttributePtr xattribute);
10
+ VALUE rxml_attr_decl_value_get(VALUE self);
11
+ #endif
@@ -0,0 +1,275 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ /*
4
+ * Document-class: LibXML::XML::Attributes
5
+ *
6
+ * Provides access to an element's attributes (XML::Attr).
7
+ *
8
+ * Basic Usage:
9
+ * require 'test_helper'
10
+ *
11
+ * doc = XML::Document.new(<some_file>)
12
+ * attributes = doc.root.attributes
13
+ *
14
+ * attributes.each do |attribute|
15
+ * ..
16
+ * end
17
+ *
18
+ * attributes['foo'] = 'bar'
19
+ * attribute = attributes.get_attribute['foo']
20
+ * attribute.value == 'foo'
21
+ *
22
+ * To access a namespaced attribute:
23
+ *
24
+ * XLINK_URI = 'http://www.w3.org/1999/xlink'
25
+ *
26
+ * attribute = attributes.get_attribute_ns(XLINK_URI, 'title')
27
+ * attribute.value = 'My title'
28
+ */
29
+
30
+ #include "ruby_libxml.h"
31
+ #include "ruby_xml_attributes.h"
32
+
33
+ VALUE cXMLAttributes;
34
+
35
+ void rxml_attributes_mark(xmlNodePtr xnode)
36
+ {
37
+ rxml_node_mark(xnode);
38
+ }
39
+
40
+ /*
41
+ * Creates a new attributes instance. Not exposed to ruby.
42
+ */
43
+ VALUE rxml_attributes_new(xmlNodePtr xnode)
44
+ {
45
+ return Data_Wrap_Struct(cXMLAttributes, rxml_attributes_mark, NULL, xnode);
46
+ }
47
+
48
+ /*
49
+ * call-seq:
50
+ * attributes.node -> XML::Node
51
+ *
52
+ * Return the node that owns this attributes list.
53
+ *
54
+ * doc.root.attributes.node == doc.root
55
+ */
56
+ VALUE rxml_attributes_node_get(VALUE self)
57
+ {
58
+ xmlNodePtr xnode;
59
+ Data_Get_Struct(self, xmlNode, xnode);
60
+ return rxml_node_wrap(xnode);
61
+ }
62
+
63
+ /*
64
+ * call-seq:
65
+ * attributes.get_attribute("name") -> (XML::Attr | XML::AtrrDecl)
66
+ *
67
+ * Returns the specified attribute. If the attribute does not
68
+ * exist but the document has an associated DTD that defines
69
+ * a default value for the attribute, then a XML::AttrDecl is
70
+ * returned.
71
+ *
72
+ * name: The name of the attribute, not including a namespace.
73
+ *
74
+ * doc.root.attributes.get_attribute("foo")
75
+ */
76
+ static VALUE rxml_attributes_get_attribute(VALUE self, VALUE name)
77
+ {
78
+ xmlNodePtr xnode;
79
+ xmlAttrPtr xattr;
80
+
81
+ name = rb_obj_as_string(name);
82
+
83
+ Data_Get_Struct(self, xmlNode, xnode);
84
+
85
+ xattr = xmlHasProp(xnode, (xmlChar*) StringValuePtr(name));
86
+
87
+ if (!xattr)
88
+ return Qnil;
89
+ else if (xattr->type == XML_ATTRIBUTE_DECL)
90
+ return rxml_attr_decl_wrap((xmlAttributePtr)xattr);
91
+ else
92
+ return rxml_attr_wrap(xattr);
93
+ }
94
+
95
+ /*
96
+ * call-seq:
97
+ * attributes.get_attribute_ns("namespace", "name") -> (XML::Attr | XML::AtrrDecl)
98
+ *
99
+ * Returns the specified attribute. If the attribute does not
100
+ * exist but the document has an associated DTD that defines
101
+ * a default value for the attribute, then a XML::AttrDecl is
102
+ * returned.
103
+ *
104
+ * namespace: The URI of the attribute's namespace.
105
+ * name: The name of the attribute, not including a namespace.
106
+ *
107
+ * doc.root.attributes.get_attribute_ns('http://www.w3.org/1999/xlink', 'href')
108
+ */
109
+ static VALUE rxml_attributes_get_attribute_ns(VALUE self, VALUE namespace,
110
+ VALUE name)
111
+ {
112
+ xmlNodePtr xnode;
113
+ xmlAttrPtr xattr;
114
+
115
+ name = rb_obj_as_string(name);
116
+
117
+ Data_Get_Struct(self, xmlNode, xnode);
118
+
119
+ xattr = xmlHasNsProp(xnode, (xmlChar*) StringValuePtr(name),
120
+ (xmlChar*) StringValuePtr(namespace));
121
+
122
+ if (!xattr)
123
+ return Qnil;
124
+ else if (xattr->type == XML_ATTRIBUTE_DECL)
125
+ return rxml_attr_decl_wrap((xmlAttributePtr)xattr);
126
+ else
127
+ return rxml_attr_wrap(xattr);
128
+ }
129
+
130
+ /*
131
+ * call-seq:
132
+ * attributes["name"] -> String
133
+ *
134
+ * Fetches an attribute value. If you want to access the underlying
135
+ * Attribute itself use get_attribute.
136
+ *
137
+ * name: The name of the attribute, not including any namespaces.
138
+ *
139
+ * doc.root.attributes['att'] -> 'some value'
140
+ */
141
+ VALUE rxml_attributes_attribute_get(VALUE self, VALUE name)
142
+ {
143
+ VALUE xattr = rxml_attributes_get_attribute(self, name);
144
+
145
+ if (NIL_P(xattr))
146
+ return Qnil;
147
+ else
148
+ return rxml_attr_value_get(xattr);
149
+ }
150
+
151
+ /*
152
+ * call-seq:
153
+ * attributes["name"] = "value"
154
+ *
155
+ * Sets an attribute value. If you want to get the Attribute itself,
156
+ * use get_attribute.
157
+ *
158
+ * name: The name of the attribute, not including any namespaces.
159
+ * value: The new value of the namespace.
160
+ *
161
+ * doc.root.attributes['att'] = 'some value'
162
+ */
163
+ VALUE rxml_attributes_attribute_set(VALUE self, VALUE name, VALUE value)
164
+ {
165
+ VALUE xattr = rxml_attributes_get_attribute(self, name);
166
+ if (NIL_P(xattr))
167
+ {
168
+ VALUE args[3];
169
+
170
+ args[0] = rxml_attributes_node_get(self);
171
+ args[1] = name;
172
+ args[2] = value;
173
+
174
+ return rb_class_new_instance(sizeof(args)/sizeof(VALUE), args, cXMLAttr);
175
+ }
176
+ else
177
+ {
178
+ return rxml_attr_value_set(xattr, value);
179
+ }
180
+ }
181
+
182
+ /*
183
+ * call-seq:
184
+ * attributes.each {block} -> XML::Attr
185
+ *
186
+ * Iterates over each attribute.
187
+ *
188
+ * doc.root.attributes.each {|attribute| puts attribute.name}
189
+ */
190
+ static VALUE rxml_attributes_each(VALUE self)
191
+ {
192
+ xmlNodePtr xnode;
193
+ xmlAttrPtr xattr;
194
+ Data_Get_Struct(self, xmlNode, xnode);
195
+
196
+ xattr = xnode->properties;
197
+
198
+ while (xattr)
199
+ {
200
+ /* Get the next attribute while we still can - the user
201
+ may remove the yielded attribute. */
202
+ xmlAttrPtr next = xattr->next;
203
+
204
+ VALUE attr = rxml_attr_wrap(xattr);
205
+ rb_yield(attr);
206
+ xattr = next;
207
+ }
208
+
209
+ return self;
210
+ }
211
+
212
+ /*
213
+ * call-seq:
214
+ * attributes.length -> Integer
215
+ *
216
+ * Returns the number of attributes.
217
+ *
218
+ * doc.root.attributes.length
219
+ */
220
+ static VALUE rxml_attributes_length(VALUE self)
221
+ {
222
+ int length = 0;
223
+ xmlNodePtr xnode;
224
+ xmlAttrPtr xattr;
225
+ Data_Get_Struct(self, xmlNode, xnode);
226
+
227
+ xattr = xnode->properties;
228
+
229
+ while (xattr)
230
+ {
231
+ length++;
232
+ xattr = xattr->next;
233
+ }
234
+
235
+ return INT2NUM(length);
236
+ }
237
+
238
+ /*
239
+ * call-seq:
240
+ * attributes.first -> XML::Attr
241
+ *
242
+ * Returns the first attribute.
243
+ *
244
+ * doc.root.attributes.first
245
+ */
246
+ static VALUE rxml_attributes_first(VALUE self)
247
+ {
248
+ xmlNodePtr xnode;
249
+ Data_Get_Struct(self, xmlNode, xnode);
250
+
251
+ if (xnode->type == XML_ELEMENT_NODE)
252
+ {
253
+ xmlAttrPtr xattr = xnode->properties;
254
+
255
+ if (xattr)
256
+ {
257
+ return rxml_attr_wrap(xattr);
258
+ }
259
+ }
260
+ return Qnil;
261
+ }
262
+
263
+ void rxml_init_attributes(void)
264
+ {
265
+ cXMLAttributes = rb_define_class_under(mXML, "Attributes", rb_cObject);
266
+ rb_include_module(cXMLAttributes, rb_mEnumerable);
267
+ rb_define_method(cXMLAttributes, "node", rxml_attributes_node_get, 0);
268
+ rb_define_method(cXMLAttributes, "get_attribute", rxml_attributes_get_attribute, 1);
269
+ rb_define_method(cXMLAttributes, "get_attribute_ns", rxml_attributes_get_attribute_ns, 2);
270
+ rb_define_method(cXMLAttributes, "[]", rxml_attributes_attribute_get, 1);
271
+ rb_define_method(cXMLAttributes, "[]=", rxml_attributes_attribute_set, 2);
272
+ rb_define_method(cXMLAttributes, "each", rxml_attributes_each, 0);
273
+ rb_define_method(cXMLAttributes, "length", rxml_attributes_length, 0);
274
+ rb_define_method(cXMLAttributes, "first", rxml_attributes_first, 0);
275
+ }
@@ -0,0 +1,15 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_ATTRIBUTES__
4
+ #define __RXML_ATTRIBUTES__
5
+
6
+ extern VALUE cXMLAttributesibutes;
7
+
8
+ void rxml_init_attributes(void);
9
+ VALUE rxml_attributes_new(xmlNodePtr xnode);
10
+
11
+ VALUE rxml_attributes_attribute_get(VALUE self, VALUE name);
12
+ VALUE rxml_attributes_attribute_set(VALUE self, VALUE name, VALUE value);
13
+
14
+
15
+ #endif
@@ -0,0 +1,85 @@
1
+ #include "ruby_libxml.h"
2
+ #include <string.h>
3
+ #include <libxml/xmlIO.h>
4
+
5
+ /*
6
+ int xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc,
7
+ xmlInputOpenCallback openFunc,
8
+ xmlInputReadCallback readFunc,
9
+ xmlInputCloseCallback closeFunc);
10
+
11
+
12
+ int (*xmlInputMatchCallback) (char const *filename);
13
+ void* (*xmlInputOpenCallback) (char const *filename);
14
+ int (*xmlInputReadCallback) (void *context,
15
+ char *buffer,
16
+ int len);
17
+ int (*xmlInputCloseCallback) (void *context);
18
+ */
19
+
20
+ typedef struct deb_doc_context
21
+ {
22
+ char *buffer;
23
+ char *bpos;
24
+ int remaining;
25
+ } deb_doc_context;
26
+
27
+ int deb_Match(char const *filename)
28
+ {
29
+ fprintf(stderr, "deb_Match: %s\n", filename);
30
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "deb://", 6))
31
+ {
32
+ return (1);
33
+ }
34
+ return (0);
35
+ }
36
+
37
+ void* deb_Open(char const *filename)
38
+ {
39
+ deb_doc_context *deb_doc;
40
+ VALUE res;
41
+
42
+ deb_doc = (deb_doc_context*) malloc(sizeof(deb_doc_context));
43
+
44
+ res = rb_funcall(rb_funcall(rb_mKernel, rb_intern("const_get"), 1,
45
+ rb_str_new2("DEBSystem")), rb_intern("document_query"), 1, rb_str_new2(filename));
46
+ deb_doc->buffer = strdup(StringValuePtr(res));
47
+ //deb_doc->buffer = strdup("<serepes>serepes</serepes>");
48
+
49
+ deb_doc->bpos = deb_doc->buffer;
50
+ deb_doc->remaining = (int)strlen(deb_doc->buffer);
51
+ return deb_doc;
52
+ }
53
+
54
+ int deb_Read(void *context, char *buffer, int len)
55
+ {
56
+ deb_doc_context *deb_doc;
57
+ int ret_len;
58
+ deb_doc = (deb_doc_context*) context;
59
+
60
+ if (len >= deb_doc->remaining)
61
+ {
62
+ ret_len = deb_doc->remaining;
63
+ }
64
+ else
65
+ {
66
+ ret_len = len;
67
+ }
68
+ deb_doc->remaining -= ret_len;
69
+ strncpy(buffer, deb_doc->bpos, ret_len);
70
+ deb_doc->bpos += ret_len;
71
+
72
+ return ret_len;
73
+ }
74
+
75
+ int deb_Close(void *context)
76
+ {
77
+ free(((deb_doc_context*) context)->buffer);
78
+ free(context);
79
+ return 1;
80
+ }
81
+
82
+ void deb_register_cbg()
83
+ {
84
+ xmlRegisterInputCallbacks(deb_Match, deb_Open, deb_Read, deb_Close);
85
+ }
@@ -0,0 +1,1133 @@
1
+ /*
2
+ * Document-class: LibXML::XML::Document
3
+ *
4
+ * The XML::Document class provides a tree based API for working
5
+ * with xml documents. You may directly create a document and
6
+ * manipulate it, or create a document from a data source by
7
+ * using an XML::Parser object.
8
+ *
9
+ * To read a document from a file:
10
+ *
11
+ * doc = XML::Document.file('my_file')
12
+ *
13
+ * To use a parser to read a document:
14
+ *
15
+ * parser = XML::Parser.file('my_file')
16
+ * doc = parser.parse
17
+ *
18
+ * To create a document from scratch:
19
+ *
20
+ * doc = XML::Document.new()
21
+ * doc.root = XML::Node.new('root_node')
22
+ * doc.root << XML::Node.new('elem1')
23
+ * doc.save(filename, :indent => true, :encoding => XML::Encoding::UTF_8)
24
+ *
25
+ * To write a document to a file:
26
+ *
27
+ * doc = XML::Document.new()
28
+ * doc.root = XML::Node.new('root_node')
29
+ * root = doc.root
30
+ *
31
+ * root << elem1 = XML::Node.new('elem1')
32
+ * elem1['attr1'] = 'val1'
33
+ * elem1['attr2'] = 'val2'
34
+ *
35
+ * root << elem2 = XML::Node.new('elem2')
36
+ * elem2['attr1'] = 'val1'
37
+ * elem2['attr2'] = 'val2'
38
+ *
39
+ * root << elem3 = XML::Node.new('elem3')
40
+ * elem3 << elem4 = XML::Node.new('elem4')
41
+ * elem3 << elem5 = XML::Node.new('elem5')
42
+ *
43
+ * elem5 << elem6 = XML::Node.new('elem6')
44
+ * elem6 << 'Content for element 6'
45
+ *
46
+ * elem3['attr'] = 'baz'
47
+ *
48
+ * doc.save(filename, :indent => true, :encoding => XML::Encoding::UTF_8)
49
+ */
50
+
51
+ #include <stdarg.h>
52
+ #include "ruby_libxml.h"
53
+ #include "ruby_xml_document.h"
54
+
55
+ VALUE cXMLDocument;
56
+
57
+
58
+ void rxml_document_mark_node_list(xmlNodePtr xnode)
59
+ {
60
+ if (xnode == NULL) return;
61
+
62
+ while (xnode != NULL)
63
+ {
64
+ rxml_document_mark_node_list(xnode->children);
65
+ rxml_node_mark(xnode);
66
+ xnode = xnode->next;
67
+ }
68
+ }
69
+
70
+ void rxml_document_mark(xmlDocPtr xdoc)
71
+ {
72
+ if (xdoc)
73
+ rxml_document_mark_node_list(xdoc->children);
74
+ }
75
+
76
+ void rxml_document_free(xmlDocPtr xdoc)
77
+ {
78
+ rxml_unregister_doc(xdoc);
79
+ xmlFreeDoc(xdoc);
80
+ }
81
+
82
+ VALUE rxml_document_wrap(xmlDocPtr xdoc)
83
+ {
84
+ VALUE result = rxml_lookup_doc(xdoc);
85
+
86
+ if (result == Qnil) {
87
+ result = Data_Wrap_Struct(cXMLDocument, rxml_document_mark, rxml_document_free, xdoc);
88
+ rxml_register_doc(xdoc, result);
89
+ }
90
+ return result;
91
+ }
92
+
93
+ /*
94
+ * call-seq:
95
+ * XML::Document.alloc(xml_version = 1.0) -> document
96
+ *
97
+ * Alocates a new XML::Document, optionally specifying the
98
+ * XML version.
99
+ */
100
+ static VALUE rxml_document_alloc(VALUE klass)
101
+ {
102
+ return Data_Wrap_Struct(klass, rxml_document_mark, rxml_document_free, NULL);
103
+ }
104
+
105
+ /*
106
+ * call-seq:
107
+ * XML::Document.initialize(xml_version = 1.0) -> document
108
+ *
109
+ * Initializes a new XML::Document, optionally specifying the
110
+ * XML version.
111
+ */
112
+ static VALUE rxml_document_initialize(int argc, VALUE *argv, VALUE self)
113
+ {
114
+ xmlDocPtr xdoc;
115
+ VALUE xmlver;
116
+
117
+ switch (argc)
118
+ {
119
+ case 0:
120
+ xmlver = rb_str_new2("1.0");
121
+ break;
122
+ case 1:
123
+ rb_scan_args(argc, argv, "01", &xmlver);
124
+ break;
125
+ default:
126
+ rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
127
+ }
128
+
129
+ Check_Type(xmlver, T_STRING);
130
+ xdoc = xmlNewDoc((xmlChar*) StringValuePtr(xmlver));
131
+ rxml_register_doc(xdoc, self);
132
+ DATA_PTR(self) = xdoc;
133
+
134
+ return self;
135
+ }
136
+
137
+ /* XML_C14N_1* constants are not defined until libxml 1.1.25, so if they
138
+ are not defined then define these constants to map to zero,
139
+ the same value as XML_C14N_1_0. */
140
+
141
+ /* XML_C14N* constants are not defined until libxml 1.1.25, so define them
142
+ if needed so things compile. */
143
+ #ifndef XML_C14N_1_0
144
+ #define XML_C14N_1_0 0
145
+ #define XML_C14N_EXCLUSIVE_1_0 XML_C14N_1_0
146
+ #define XML_C14N_1_1 XML_C14N_1_0
147
+ #endif
148
+
149
+ /*
150
+ * :call-seq:
151
+ * document.canonicalize -> String
152
+ * document.canonicalize(options) -> String
153
+ *
154
+ * Returns a string containing the canonicalized form of the document.
155
+ * Implemented to include all of the functionality of the libxml2
156
+ * {xmlC14NDocDumpMemory}[http://xmlsoft.org/html/libxml-c14n.html#xmlC14NDocDumpMemory]
157
+ * method.
158
+ *
159
+ * === Options
160
+ * [comments]
161
+ * * *Type:* Boolean
162
+ * * *Default:* false
163
+ * Specifies if comments should be output.
164
+ * * Must be boolean, otherwise defaults to false.
165
+ * [inclusive_ns_prefixes]
166
+ * * *Type:* Array of strings
167
+ * * *Default:* empty array
168
+ * Array of namespace prefixes to include in exclusive canonicalization only.
169
+ * * The last item in the list is reserved for a NULL value because the C method demands it, therefore
170
+ * up to the first 255 valid entries will be used.
171
+ * * <em>Only used for *XML_C14N_EXCLUSIVE_1_0* mode. Ignored otherwise.</em>
172
+ * [mode]
173
+ * * *Type:* XML::Document Constant
174
+ * * *Default:* XML_C14N_1_0
175
+ * Specifies the mode of canonicalization.
176
+ * * *NOTE:* XML_C14N_1_1 may not be fully implemented upon compilation due to C library compatibility.
177
+ * Please check if XML_C14N_1_0 and XML_C14N_1_1 are the same value prior to using XML_C14N_1_1.
178
+ * [nodes]
179
+ * * *Type:* Array of XML::Node objects
180
+ * * *Default:* empty array
181
+ * XML::Nodes to include in the canonicalization process
182
+ * * For large lists of more than 256 valid namespaces, up to the first 256 valid entries will be used.
183
+ */
184
+ #define C14N_NS_LIMIT 256
185
+ #define C14N_NODESET_LIMIT 256
186
+
187
+ static VALUE
188
+ rxml_document_canonicalize(int argc, VALUE *argv, VALUE self)
189
+ {
190
+ VALUE result = Qnil;
191
+ xmlDocPtr xdoc;
192
+ xmlChar *buffer = NULL;
193
+ VALUE option_hash = Qnil;
194
+ VALUE o_nodes = Qnil;
195
+
196
+ // :comments option
197
+ int comments = 0;
198
+ // :mode option
199
+ int c14n_mode = XML_C14N_1_0;
200
+ // :inclusive_ns_prefixes option (ARRAY)
201
+
202
+ xmlChar * inc_ns_prefixes_ptr[C14N_NS_LIMIT];
203
+
204
+ // :nodes option (ARRAY)
205
+ xmlNodePtr node_ptr_array[C14N_NODESET_LIMIT];
206
+ xmlNodeSet nodeset = {
207
+ 0, C14N_NODESET_LIMIT, NULL
208
+ };
209
+
210
+ /* At least one NULL value must be defined in the array or the extension will
211
+ * segfault when using XML_C14N_EXCLUSIVE_1_0 mode.
212
+ * API docs: "list of inclusive namespace prefixes ended with a NULL"
213
+ */
214
+ inc_ns_prefixes_ptr[0] = NULL;
215
+
216
+ rb_scan_args(argc, argv, "01", &option_hash);
217
+ // Do stuff if ruby hash passed as argument
218
+ if (!NIL_P(option_hash))
219
+ {
220
+ VALUE o_comments = Qnil;
221
+ VALUE o_mode = Qnil;
222
+ VALUE o_i_ns_prefixes = Qnil;
223
+
224
+ Check_Type(option_hash, T_HASH);
225
+
226
+ o_comments = rb_hash_aref(option_hash, ID2SYM(rb_intern("comments")));
227
+ comments = (RTEST(o_comments) ? 1 : 0);
228
+
229
+ o_mode = rb_hash_aref(option_hash, ID2SYM(rb_intern("mode")));
230
+ if (!NIL_P(o_mode))
231
+ {
232
+ Check_Type(o_mode, T_FIXNUM);
233
+ c14n_mode = NUM2INT(o_mode);
234
+ //TODO: clean this up
235
+ //if (c14n_mode > 2) { c14n_mode = 0; }
236
+ //mode_int = (NUM2INT(o_mode) > 2 ? 0 : NUM2INT(o_mode));
237
+ }
238
+
239
+ o_i_ns_prefixes = rb_hash_aref(option_hash, ID2SYM(rb_intern("inclusive_ns_prefixes")));
240
+ if (!NIL_P(o_i_ns_prefixes))
241
+ {
242
+ int i;
243
+ int p = 0; //pointer array index
244
+ VALUE *list_in = NULL;
245
+ long list_size = 0;
246
+
247
+ Check_Type(o_i_ns_prefixes, T_ARRAY);
248
+ list_in = RARRAY_PTR(o_i_ns_prefixes);
249
+ list_size = RARRAY_LEN(o_i_ns_prefixes);
250
+
251
+ if (list_size > 0)
252
+ {
253
+ for(i=0; i < list_size; ++i) {
254
+ if (p >= C14N_NS_LIMIT) { break; }
255
+
256
+ if (RTEST(list_in[i]))
257
+ {
258
+ if (TYPE(list_in[i]) == T_STRING)
259
+ {
260
+ inc_ns_prefixes_ptr[p] = (xmlChar *)StringValueCStr(list_in[i]);
261
+ p++;
262
+ }
263
+ }
264
+ }
265
+ }
266
+
267
+ // ensure p is not out of bound
268
+ p = (p >= C14N_NS_LIMIT ? (C14N_NS_LIMIT-1) : p);
269
+
270
+ // API docs: "list of inclusive namespace prefixes ended with a NULL"
271
+ // Set last element to NULL
272
+ inc_ns_prefixes_ptr[p] = NULL;
273
+ }
274
+ //o_ns_prefixes will free at end of block
275
+
276
+ o_nodes = rb_hash_aref(option_hash, ID2SYM(rb_intern("nodes")));
277
+ if (!NIL_P(o_nodes))
278
+ {
279
+ int i;
280
+ int p = 0; // index of pointer array
281
+ VALUE * list_in = NULL;
282
+ long node_list_size = 0;
283
+
284
+ if (CLASS_OF(o_nodes) == cXMLXPathObject)
285
+ {
286
+ o_nodes = rb_funcall(o_nodes, rb_intern("to_a"), 0);
287
+ }
288
+ else
289
+ {
290
+ Check_Type(o_nodes, T_ARRAY);
291
+ }
292
+ list_in = RARRAY_PTR(o_nodes);
293
+ node_list_size = RARRAY_LEN(o_nodes);
294
+
295
+ for (i=0; i < node_list_size; ++i)
296
+ {
297
+ if (p >= C14N_NODESET_LIMIT) { break; }
298
+
299
+ if (RTEST(list_in[i]))
300
+ {
301
+ xmlNodePtr node_ptr;
302
+ Data_Get_Struct(list_in[i], xmlNode, node_ptr);
303
+ node_ptr_array[p] = node_ptr;
304
+ p++;
305
+ }
306
+ }
307
+
308
+ // Need to set values in nodeset struct
309
+ nodeset.nodeNr = (node_list_size > C14N_NODESET_LIMIT ?
310
+ C14N_NODESET_LIMIT :
311
+ (int)node_list_size);
312
+ nodeset.nodeTab = node_ptr_array;
313
+ }
314
+ }//option_hash
315
+
316
+ Data_Get_Struct(self, xmlDoc, xdoc);
317
+ xmlC14NDocDumpMemory(xdoc,
318
+ (nodeset.nodeNr == 0 ? NULL : &nodeset),
319
+ c14n_mode,
320
+ inc_ns_prefixes_ptr,
321
+ comments,
322
+ &buffer);
323
+
324
+ if (buffer)
325
+ {
326
+ result = rxml_new_cstr( buffer, NULL);
327
+ xmlFree(buffer);
328
+ }
329
+
330
+ return result;
331
+ }
332
+
333
+
334
+ /*
335
+ * call-seq:
336
+ * document.compression -> num
337
+ *
338
+ * Obtain this document's compression mode identifier.
339
+ */
340
+ static VALUE rxml_document_compression_get(VALUE self)
341
+ {
342
+ #ifdef HAVE_ZLIB_H
343
+ xmlDocPtr xdoc;
344
+
345
+ int compmode;
346
+ Data_Get_Struct(self, xmlDoc, xdoc);
347
+
348
+ compmode = xmlGetDocCompressMode(xdoc);
349
+ if (compmode == -1)
350
+ return(Qnil);
351
+ else
352
+ return(INT2NUM(compmode));
353
+ #else
354
+ rb_warn("libxml not compiled with zlib support");
355
+ return (Qfalse);
356
+ #endif
357
+ }
358
+
359
+ /*
360
+ * call-seq:
361
+ * document.compression = num
362
+ *
363
+ * Set this document's compression mode.
364
+ */
365
+ static VALUE rxml_document_compression_set(VALUE self, VALUE num)
366
+ {
367
+ #ifdef HAVE_ZLIB_H
368
+ xmlDocPtr xdoc;
369
+
370
+ int compmode;
371
+ Check_Type(num, T_FIXNUM);
372
+ Data_Get_Struct(self, xmlDoc, xdoc);
373
+
374
+ if (xdoc == NULL)
375
+ {
376
+ return(Qnil);
377
+ }
378
+ else
379
+ {
380
+ xmlSetDocCompressMode(xdoc, NUM2INT(num));
381
+
382
+ compmode = xmlGetDocCompressMode(xdoc);
383
+ if (compmode == -1)
384
+ return(Qnil);
385
+ else
386
+ return(INT2NUM(compmode));
387
+ }
388
+ #else
389
+ rb_warn("libxml compiled without zlib support");
390
+ return (Qfalse);
391
+ #endif
392
+ }
393
+
394
+ /*
395
+ * call-seq:
396
+ * document.compression? -> (true|false)
397
+ *
398
+ * Determine whether this document is compressed.
399
+ */
400
+ static VALUE rxml_document_compression_q(VALUE self)
401
+ {
402
+ #ifdef HAVE_ZLIB_H
403
+ xmlDocPtr xdoc;
404
+
405
+ Data_Get_Struct(self, xmlDoc, xdoc);
406
+
407
+ if (xdoc->compression != -1)
408
+ return(Qtrue);
409
+ else
410
+ return(Qfalse);
411
+ #else
412
+ rb_warn("libxml compiled without zlib support");
413
+ return (Qfalse);
414
+ #endif
415
+ }
416
+
417
+ /*
418
+ * call-seq:
419
+ * document.child -> node
420
+ *
421
+ * Get this document's child node.
422
+ */
423
+ static VALUE rxml_document_child_get(VALUE self)
424
+ {
425
+ xmlDocPtr xdoc;
426
+ Data_Get_Struct(self, xmlDoc, xdoc);
427
+
428
+ if (xdoc->children == NULL)
429
+ return (Qnil);
430
+
431
+ return rxml_node_wrap(xdoc->children);
432
+ }
433
+
434
+ /*
435
+ * call-seq:
436
+ * document.child? -> (true|false)
437
+ *
438
+ * Determine whether this document has a child node.
439
+ */
440
+ static VALUE rxml_document_child_q(VALUE self)
441
+ {
442
+ xmlDocPtr xdoc;
443
+ Data_Get_Struct(self, xmlDoc, xdoc);
444
+
445
+ if (xdoc->children == NULL)
446
+ return (Qfalse);
447
+ else
448
+ return (Qtrue);
449
+ }
450
+
451
+
452
+ /*
453
+ * call-seq:
454
+ * node.debug -> true|false
455
+ *
456
+ * Print libxml debugging information to stdout.
457
+ * Requires that libxml was compiled with debugging enabled.
458
+ */
459
+ static VALUE rxml_document_debug(VALUE self)
460
+ {
461
+ #ifdef LIBXML_DEBUG_ENABLED
462
+ xmlDocPtr xdoc;
463
+ Data_Get_Struct(self, xmlDoc, xdoc);
464
+ xmlDebugDumpDocument(NULL, xdoc);
465
+ return Qtrue;
466
+ #else
467
+ rb_warn("libxml was compiled without debugging support.");
468
+ return Qfalse;
469
+ #endif
470
+ }
471
+
472
+ /*
473
+ * call-seq:
474
+ * document.encoding -> XML::Encoding::UTF_8
475
+ *
476
+ * Returns the LibXML encoding constant specified by this document.
477
+ */
478
+ static VALUE rxml_document_encoding_get(VALUE self)
479
+ {
480
+ xmlDocPtr xdoc;
481
+ const char *xencoding;
482
+ Data_Get_Struct(self, xmlDoc, xdoc);
483
+
484
+ xencoding = (const char*)xdoc->encoding;
485
+ return INT2NUM(xmlParseCharEncoding(xencoding));
486
+ }
487
+
488
+
489
+ /*
490
+ * call-seq:
491
+ * document.rb_encoding -> Encoding
492
+ *
493
+ * Returns the Ruby encoding specified by this document
494
+ * (available on Ruby 1.9.x and higher).
495
+ */
496
+ #ifdef HAVE_RUBY_ENCODING_H
497
+ static VALUE rxml_document_rb_encoding_get(VALUE self)
498
+ {
499
+ xmlDocPtr xdoc;
500
+ rb_encoding* rbencoding;
501
+ Data_Get_Struct(self, xmlDoc, xdoc);
502
+
503
+ rbencoding = rxml_xml_encoding_to_rb_encoding(mXMLEncoding, xmlParseCharEncoding((const char*)xdoc->encoding));
504
+ return rb_enc_from_encoding(rbencoding);
505
+ }
506
+ #endif
507
+
508
+ /*
509
+ * call-seq:
510
+ * document.encoding = XML::Encoding::UTF_8
511
+ *
512
+ * Set the encoding for this document.
513
+ */
514
+ static VALUE rxml_document_encoding_set(VALUE self, VALUE encoding)
515
+ {
516
+ xmlDocPtr xdoc;
517
+ const char* xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(encoding));
518
+
519
+ Data_Get_Struct(self, xmlDoc, xdoc);
520
+
521
+ if (xdoc->encoding != NULL)
522
+ xmlFree((xmlChar *) xdoc->encoding);
523
+
524
+ xdoc->encoding = xmlStrdup((xmlChar *)xencoding);
525
+ return self;
526
+ }
527
+
528
+ /*
529
+ * call-seq:
530
+ * document.import(node) -> XML::Node
531
+ *
532
+ * Creates a copy of the node that can be inserted into the
533
+ * current document.
534
+ *
535
+ * IMPORTANT - The returned node MUST be inserted into the document.
536
+ * This is because the returned node refereces internal LibXML data
537
+ * structures owned by the document. Therefore, if the document is
538
+ * is freed before the the node is freed a segmentation fault will occur.
539
+ */
540
+ static VALUE rxml_document_import(VALUE self, VALUE node)
541
+ {
542
+ xmlDocPtr xdoc;
543
+ xmlNodePtr xnode, xresult;
544
+
545
+ Data_Get_Struct(self, xmlDoc, xdoc);
546
+ Data_Get_Struct(node, xmlNode, xnode);
547
+
548
+ xresult = xmlDocCopyNode(xnode, xdoc, 1);
549
+
550
+ if (xresult == NULL)
551
+ rxml_raise(&xmlLastError);
552
+
553
+ return rxml_node_wrap(xresult);
554
+ }
555
+
556
+ /*
557
+ * call-seq:
558
+ * document.last -> node
559
+ *
560
+ * Obtain the last node.
561
+ */
562
+ static VALUE rxml_document_last_get(VALUE self)
563
+ {
564
+ xmlDocPtr xdoc;
565
+
566
+ Data_Get_Struct(self, xmlDoc, xdoc);
567
+
568
+ if (xdoc->last == NULL)
569
+ return (Qnil);
570
+
571
+ return rxml_node_wrap(xdoc->last);
572
+ }
573
+
574
+ /*
575
+ * call-seq:
576
+ * document.last? -> (true|false)
577
+ *
578
+ * Determine whether there is a last node.
579
+ */
580
+ static VALUE rxml_document_last_q(VALUE self)
581
+ {
582
+ xmlDocPtr xdoc;
583
+
584
+ Data_Get_Struct(self, xmlDoc, xdoc);
585
+
586
+ if (xdoc->last == NULL)
587
+ return (Qfalse);
588
+ else
589
+ return (Qtrue);
590
+ }
591
+
592
+ /*
593
+ * call-seq:
594
+ * document.next -> node
595
+ *
596
+ * Obtain the next node.
597
+ */
598
+ static VALUE rxml_document_next_get(VALUE self)
599
+ {
600
+ xmlDocPtr xdoc;
601
+
602
+ Data_Get_Struct(self, xmlDoc, xdoc);
603
+
604
+ if (xdoc->next == NULL)
605
+ return (Qnil);
606
+
607
+ return rxml_node_wrap(xdoc->next);
608
+ }
609
+
610
+ /*
611
+ * call-seq:
612
+ * document.next? -> (true|false)
613
+ *
614
+ * Determine whether there is a next node.
615
+ */
616
+ static VALUE rxml_document_next_q(VALUE self)
617
+ {
618
+ xmlDocPtr xdoc;
619
+
620
+ Data_Get_Struct(self, xmlDoc, xdoc);
621
+
622
+ if (xdoc->next == NULL)
623
+ return (Qfalse);
624
+ else
625
+ return (Qtrue);
626
+ }
627
+
628
+ /*
629
+ * call-seq:
630
+ * node.type -> num
631
+ *
632
+ * Obtain this node's type identifier.
633
+ */
634
+ static VALUE rxml_document_node_type(VALUE self)
635
+ {
636
+ xmlNodePtr xnode;
637
+ Data_Get_Struct(self, xmlNode, xnode);
638
+ return (INT2NUM(xnode->type));
639
+ }
640
+
641
+ /*
642
+ * call-seq:
643
+ * document.parent -> node
644
+ *
645
+ * Obtain the parent node.
646
+ */
647
+ static VALUE rxml_document_parent_get(VALUE self)
648
+ {
649
+ xmlDocPtr xdoc;
650
+
651
+ Data_Get_Struct(self, xmlDoc, xdoc);
652
+
653
+ if (xdoc->parent == NULL)
654
+ return (Qnil);
655
+
656
+ return rxml_node_wrap(xdoc->parent);
657
+ }
658
+
659
+ /*
660
+ * call-seq:
661
+ * document.parent? -> (true|false)
662
+ *
663
+ * Determine whether there is a parent node.
664
+ */
665
+ static VALUE rxml_document_parent_q(VALUE self)
666
+ {
667
+ xmlDocPtr xdoc;
668
+
669
+ Data_Get_Struct(self, xmlDoc, xdoc);
670
+
671
+ if (xdoc->parent == NULL)
672
+ return (Qfalse);
673
+ else
674
+ return (Qtrue);
675
+ }
676
+
677
+ /*
678
+ * call-seq:
679
+ * document.prev -> node
680
+ *
681
+ * Obtain the previous node.
682
+ */
683
+ static VALUE rxml_document_prev_get(VALUE self)
684
+ {
685
+ xmlDocPtr xdoc;
686
+
687
+ Data_Get_Struct(self, xmlDoc, xdoc);
688
+
689
+ if (xdoc->prev == NULL)
690
+ return (Qnil);
691
+
692
+ return rxml_node_wrap(xdoc->prev);
693
+ }
694
+
695
+ /*
696
+ * call-seq:
697
+ * document.prev? -> (true|false)
698
+ *
699
+ * Determine whether there is a previous node.
700
+ */
701
+ static VALUE rxml_document_prev_q(VALUE self)
702
+ {
703
+ xmlDocPtr xdoc;
704
+
705
+ Data_Get_Struct(self, xmlDoc, xdoc);
706
+
707
+ if (xdoc->prev == NULL)
708
+ return (Qfalse);
709
+ else
710
+ return (Qtrue);
711
+ }
712
+
713
+ /*
714
+ * call-seq:
715
+ * document.root -> node
716
+ *
717
+ * Obtain the root node.
718
+ */
719
+ static VALUE rxml_document_root_get(VALUE self)
720
+ {
721
+ xmlDocPtr xdoc;
722
+ xmlNodePtr root;
723
+
724
+ Data_Get_Struct(self, xmlDoc, xdoc);
725
+ root = xmlDocGetRootElement(xdoc);
726
+
727
+ if (root == NULL)
728
+ return (Qnil);
729
+
730
+ return rxml_node_wrap(root);
731
+ }
732
+
733
+ /*
734
+ * call-seq:
735
+ * document.root = node
736
+ *
737
+ * Set the root node.
738
+ */
739
+ static VALUE rxml_document_root_set(VALUE self, VALUE node)
740
+ {
741
+ xmlDocPtr xdoc;
742
+ xmlNodePtr xnode;
743
+
744
+ if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
745
+ rb_raise(rb_eTypeError, "must pass an XML::Node type object");
746
+
747
+ Data_Get_Struct(self, xmlDoc, xdoc);
748
+ Data_Get_Struct(node, xmlNode, xnode);
749
+
750
+ if (xnode->doc != NULL && xnode->doc != xdoc)
751
+ rb_raise(eXMLError, "Nodes belong to different documents. You must first import the node by calling XML::Document.import");
752
+
753
+ xmlDocSetRootElement(xdoc, xnode);
754
+ return node;
755
+ }
756
+
757
+ /*
758
+ * call-seq:
759
+ * document.save(filename) -> int
760
+ * document.save(filename, :indent => true, :encoding => XML::Encoding::UTF_8) -> int
761
+ *
762
+ * Saves a document to a file. You may provide an optional hash table
763
+ * to control how the string is generated. Valid options are:
764
+ *
765
+ * :indent - Specifies if the string should be indented. The default value
766
+ * is true. Note that indentation is only added if both :indent is
767
+ * true and XML.indent_tree_output is true. If :indent is set to false,
768
+ * then both indentation and line feeds are removed from the result.
769
+ *
770
+ * :encoding - Specifies the output encoding of the string. It
771
+ * defaults to the original encoding of the document (see
772
+ * #encoding. To override the orginal encoding, use one of the
773
+ * XML::Encoding encoding constants. */
774
+ static VALUE rxml_document_save(int argc, VALUE *argv, VALUE self)
775
+ {
776
+ VALUE options = Qnil;
777
+ VALUE filename = Qnil;
778
+ xmlDocPtr xdoc;
779
+ int indent = 1;
780
+ const char *xfilename;
781
+ const xmlChar *xencoding;
782
+ int length;
783
+
784
+ rb_scan_args(argc, argv, "11", &filename, &options);
785
+
786
+ Check_Type(filename, T_STRING);
787
+ xfilename = StringValuePtr(filename);
788
+
789
+ Data_Get_Struct(self, xmlDoc, xdoc);
790
+ xencoding = xdoc->encoding;
791
+
792
+ if (!NIL_P(options))
793
+ {
794
+ VALUE rencoding, rindent;
795
+ Check_Type(options, T_HASH);
796
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
797
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
798
+
799
+ if (rindent == Qfalse)
800
+ indent = 0;
801
+
802
+ if (rencoding != Qnil)
803
+ {
804
+ xencoding = (const xmlChar*)xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
805
+ if (!xencoding)
806
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
807
+ }
808
+ }
809
+
810
+ length = xmlSaveFormatFileEnc(xfilename, xdoc, (const char*)xencoding, indent);
811
+
812
+ if (length == -1)
813
+ rxml_raise(&xmlLastError);
814
+
815
+ return (INT2NUM(length));
816
+ }
817
+
818
+ /*
819
+ * call-seq:
820
+ * document.standalone? -> (true|false)
821
+ *
822
+ * Determine whether this is a standalone document.
823
+ */
824
+ static VALUE rxml_document_standalone_q(VALUE self)
825
+ {
826
+ xmlDocPtr xdoc;
827
+
828
+ Data_Get_Struct(self, xmlDoc, xdoc);
829
+ if (xdoc->standalone)
830
+ return (Qtrue);
831
+ else
832
+ return (Qfalse);
833
+ }
834
+
835
+ /*
836
+ * call-seq:
837
+ * document.to_s -> "string"
838
+ * document.to_s(:indent => true, :encoding => XML::Encoding::UTF_8) -> "string"
839
+ *
840
+ * Converts a document, and all of its children, to a string representation.
841
+ * You may provide an optional hash table to control how the string is
842
+ * generated. Valid options are:
843
+ *
844
+ * :indent - Specifies if the string should be indented. The default value
845
+ * is true. Note that indentation is only added if both :indent is
846
+ * true and XML.indent_tree_output is true. If :indent is set to false,
847
+ * then both indentation and line feeds are removed from the result.
848
+ *
849
+ * :encoding - Specifies the output encoding of the string. It
850
+ * defaults to XML::Encoding::UTF8. To change it, use one of the
851
+ * XML::Encoding encoding constants. */
852
+ static VALUE rxml_document_to_s(int argc, VALUE *argv, VALUE self)
853
+ {
854
+ VALUE result;
855
+ VALUE options = Qnil;
856
+ xmlDocPtr xdoc;
857
+ int indent = 1;
858
+ const xmlChar *xencoding = (const xmlChar*) "UTF-8";
859
+ xmlChar *buffer;
860
+ int length;
861
+
862
+ rb_scan_args(argc, argv, "01", &options);
863
+
864
+ if (!NIL_P(options))
865
+ {
866
+ VALUE rencoding, rindent;
867
+ Check_Type(options, T_HASH);
868
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
869
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
870
+
871
+ if (rindent == Qfalse)
872
+ indent = 0;
873
+
874
+ if (rencoding != Qnil)
875
+ {
876
+ xencoding = (const xmlChar*)xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
877
+ if (!xencoding)
878
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
879
+ }
880
+ }
881
+
882
+ Data_Get_Struct(self, xmlDoc, xdoc);
883
+ xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, (const char*)xencoding, indent);
884
+
885
+ result = rxml_new_cstr(buffer, xencoding);
886
+ xmlFree(buffer);
887
+ return result;
888
+ }
889
+
890
+ /*
891
+ * call-seq:
892
+ * document.url -> "url"
893
+ *
894
+ * Obtain this document's source URL, if any.
895
+ */
896
+ static VALUE rxml_document_url_get(VALUE self)
897
+ {
898
+ xmlDocPtr xdoc;
899
+
900
+ Data_Get_Struct(self, xmlDoc, xdoc);
901
+ if (xdoc->URL == NULL)
902
+ return (Qnil);
903
+ else
904
+ return (rxml_new_cstr( xdoc->URL, NULL));
905
+ }
906
+
907
+ /*
908
+ * call-seq:
909
+ * document.version -> "version"
910
+ *
911
+ * Obtain the XML version specified by this document.
912
+ */
913
+ static VALUE rxml_document_version_get(VALUE self)
914
+ {
915
+ xmlDocPtr xdoc;
916
+
917
+ Data_Get_Struct(self, xmlDoc, xdoc);
918
+ if (xdoc->version == NULL)
919
+ return (Qnil);
920
+ else
921
+ return (rxml_new_cstr( xdoc->version, NULL));
922
+ }
923
+
924
+ /*
925
+ * call-seq:
926
+ * document.xhtml? -> (true|false)
927
+ *
928
+ * Determine whether this is an XHTML document.
929
+ */
930
+ static VALUE rxml_document_xhtml_q(VALUE self)
931
+ {
932
+ xmlDocPtr xdoc;
933
+ xmlDtdPtr xdtd;
934
+ Data_Get_Struct(self, xmlDoc, xdoc);
935
+ xdtd = xmlGetIntSubset(xdoc);
936
+ if (xdtd != NULL && xmlIsXHTML(xdtd->SystemID, xdtd->ExternalID) > 0)
937
+ return (Qtrue);
938
+ else
939
+ return (Qfalse);
940
+ }
941
+
942
+ /*
943
+ * call-seq:
944
+ * document.xinclude -> num
945
+ *
946
+ * Process xinclude directives in this document.
947
+ */
948
+ static VALUE rxml_document_xinclude(VALUE self)
949
+ {
950
+ #ifdef LIBXML_XINCLUDE_ENABLED
951
+ xmlDocPtr xdoc;
952
+
953
+ int ret;
954
+
955
+ Data_Get_Struct(self, xmlDoc, xdoc);
956
+ ret = xmlXIncludeProcess(xdoc);
957
+ if (ret >= 0)
958
+ {
959
+ return(INT2NUM(ret));
960
+ }
961
+ else
962
+ {
963
+ rxml_raise(&xmlLastError);
964
+ return Qnil;
965
+ }
966
+ #else
967
+ rb_warn(
968
+ "libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
969
+ return (Qfalse);
970
+ #endif
971
+ }
972
+
973
+ /*
974
+ * call-seq:
975
+ * document.order_elements!
976
+ *
977
+ * Call this routine to speed up XPath computation on static documents.
978
+ * This stamps all the element nodes with the document order.
979
+ */
980
+ static VALUE rxml_document_order_elements(VALUE self)
981
+ {
982
+ xmlDocPtr xdoc;
983
+
984
+ Data_Get_Struct(self, xmlDoc, xdoc);
985
+ return LONG2FIX(xmlXPathOrderDocElems(xdoc));
986
+ }
987
+
988
+ /*
989
+ * call-seq:
990
+ * document.validate_schema(schema)
991
+ *
992
+ * Validate this document against the specified XML::Schema.
993
+ * If the document is valid the method returns true. Otherwise an
994
+ * exception is raised with validation information.
995
+ */
996
+ static VALUE rxml_document_validate_schema(VALUE self, VALUE schema)
997
+ {
998
+ xmlSchemaValidCtxtPtr vptr;
999
+ xmlDocPtr xdoc;
1000
+ xmlSchemaPtr xschema;
1001
+ int is_invalid;
1002
+
1003
+ Data_Get_Struct(self, xmlDoc, xdoc);
1004
+ Data_Get_Struct(schema, xmlSchema, xschema);
1005
+
1006
+ vptr = xmlSchemaNewValidCtxt(xschema);
1007
+
1008
+ is_invalid = xmlSchemaValidateDoc(vptr, xdoc);
1009
+ xmlSchemaFreeValidCtxt(vptr);
1010
+ if (is_invalid)
1011
+ {
1012
+ rxml_raise(&xmlLastError);
1013
+ return Qfalse;
1014
+ }
1015
+ else
1016
+ {
1017
+ return Qtrue;
1018
+ }
1019
+ }
1020
+
1021
+ /*
1022
+ * call-seq:
1023
+ * document.validate_relaxng(relaxng)
1024
+ *
1025
+ * Validate this document against the specified XML::RelaxNG.
1026
+ * If the document is valid the method returns true. Otherwise an
1027
+ * exception is raised with validation information.
1028
+ */
1029
+ static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng)
1030
+ {
1031
+ xmlRelaxNGValidCtxtPtr vptr;
1032
+ xmlDocPtr xdoc;
1033
+ xmlRelaxNGPtr xrelaxng;
1034
+ int is_invalid;
1035
+
1036
+ Data_Get_Struct(self, xmlDoc, xdoc);
1037
+ Data_Get_Struct(relaxng, xmlRelaxNG, xrelaxng);
1038
+
1039
+ vptr = xmlRelaxNGNewValidCtxt(xrelaxng);
1040
+
1041
+ is_invalid = xmlRelaxNGValidateDoc(vptr, xdoc);
1042
+ xmlRelaxNGFreeValidCtxt(vptr);
1043
+ if (is_invalid)
1044
+ {
1045
+ rxml_raise(&xmlLastError);
1046
+ return Qfalse;
1047
+ }
1048
+ else
1049
+ {
1050
+ return Qtrue;
1051
+ }
1052
+ }
1053
+
1054
+ /*
1055
+ * call-seq:
1056
+ * document.validate(dtd) -> (true|false)
1057
+ *
1058
+ * Validate this document against the specified XML::DTD.
1059
+ * If the document is valid the method returns true. Otherwise an
1060
+ * exception is raised with validation information.
1061
+ */
1062
+ static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd)
1063
+ {
1064
+ xmlValidCtxt ctxt;
1065
+ xmlDocPtr xdoc;
1066
+ xmlDtdPtr xdtd;
1067
+
1068
+ Data_Get_Struct(self, xmlDoc, xdoc);
1069
+ Data_Get_Struct(dtd, xmlDtd, xdtd);
1070
+
1071
+ /* Setup context */
1072
+ memset(&ctxt, 0, sizeof(xmlValidCtxt));
1073
+
1074
+ if (xmlValidateDtd(&ctxt, xdoc, xdtd))
1075
+ {
1076
+ return Qtrue;
1077
+ }
1078
+ else
1079
+ {
1080
+ rxml_raise(&xmlLastError);
1081
+ return Qfalse;
1082
+ }
1083
+ }
1084
+
1085
+ void rxml_init_document(void)
1086
+ {
1087
+ cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
1088
+ rb_define_alloc_func(cXMLDocument, rxml_document_alloc);
1089
+
1090
+ /* Original C14N 1.0 spec */
1091
+ rb_define_const(cXMLDocument, "XML_C14N_1_0", INT2NUM(XML_C14N_1_0));
1092
+ /* Exclusive C14N 1.0 spec */
1093
+ rb_define_const(cXMLDocument, "XML_C14N_EXCLUSIVE_1_0", INT2NUM(XML_C14N_EXCLUSIVE_1_0));
1094
+ /* C14N 1.1 spec */
1095
+ rb_define_const(cXMLDocument, "XML_C14N_1_1", INT2NUM(XML_C14N_1_1));
1096
+
1097
+ rb_define_method(cXMLDocument, "initialize", rxml_document_initialize, -1);
1098
+ rb_define_method(cXMLDocument, "canonicalize", rxml_document_canonicalize, -1);
1099
+ rb_define_method(cXMLDocument, "child", rxml_document_child_get, 0);
1100
+ rb_define_method(cXMLDocument, "child?", rxml_document_child_q, 0);
1101
+ rb_define_method(cXMLDocument, "compression", rxml_document_compression_get, 0);
1102
+ rb_define_method(cXMLDocument, "compression=", rxml_document_compression_set, 1);
1103
+ rb_define_method(cXMLDocument, "compression?", rxml_document_compression_q, 0);
1104
+ rb_define_method(cXMLDocument, "debug", rxml_document_debug, 0);
1105
+ rb_define_method(cXMLDocument, "encoding", rxml_document_encoding_get, 0);
1106
+ #ifdef HAVE_RUBY_ENCODING_H
1107
+ rb_define_method(cXMLDocument, "rb_encoding", rxml_document_rb_encoding_get, 0);
1108
+ #endif
1109
+ rb_define_method(cXMLDocument, "encoding=", rxml_document_encoding_set, 1);
1110
+ rb_define_method(cXMLDocument, "import", rxml_document_import, 1);
1111
+ rb_define_method(cXMLDocument, "last", rxml_document_last_get, 0);
1112
+ rb_define_method(cXMLDocument, "last?", rxml_document_last_q, 0);
1113
+ rb_define_method(cXMLDocument, "next", rxml_document_next_get, 0);
1114
+ rb_define_method(cXMLDocument, "next?", rxml_document_next_q, 0);
1115
+ rb_define_method(cXMLDocument, "node_type", rxml_document_node_type, 0);
1116
+ rb_define_method(cXMLDocument, "order_elements!", rxml_document_order_elements, 0);
1117
+ rb_define_method(cXMLDocument, "parent", rxml_document_parent_get, 0);
1118
+ rb_define_method(cXMLDocument, "parent?", rxml_document_parent_q, 0);
1119
+ rb_define_method(cXMLDocument, "prev", rxml_document_prev_get, 0);
1120
+ rb_define_method(cXMLDocument, "prev?", rxml_document_prev_q, 0);
1121
+ rb_define_method(cXMLDocument, "root", rxml_document_root_get, 0);
1122
+ rb_define_method(cXMLDocument, "root=", rxml_document_root_set, 1);
1123
+ rb_define_method(cXMLDocument, "save", rxml_document_save, -1);
1124
+ rb_define_method(cXMLDocument, "standalone?", rxml_document_standalone_q, 0);
1125
+ rb_define_method(cXMLDocument, "to_s", rxml_document_to_s, -1);
1126
+ rb_define_method(cXMLDocument, "url", rxml_document_url_get, 0);
1127
+ rb_define_method(cXMLDocument, "version", rxml_document_version_get, 0);
1128
+ rb_define_method(cXMLDocument, "xhtml?", rxml_document_xhtml_q, 0);
1129
+ rb_define_method(cXMLDocument, "xinclude", rxml_document_xinclude, 0);
1130
+ rb_define_method(cXMLDocument, "validate", rxml_document_validate_dtd, 1);
1131
+ rb_define_method(cXMLDocument, "validate_schema", rxml_document_validate_schema, 1);
1132
+ rb_define_method(cXMLDocument, "validate_relaxng", rxml_document_validate_relaxng, 1);
1133
+ }