libxml-ruby 2.8.0 → 3.2.1

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