libxml-ruby 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +49 -0
- data/LICENSE +22 -0
- data/README +129 -0
- data/Rakefile +197 -0
- data/TODO +84 -0
- data/ext/xml/cbg.c +76 -0
- data/ext/xml/extconf.rb +95 -0
- data/ext/xml/libxml.c +86 -0
- data/ext/xml/libxml.h +79 -0
- data/ext/xml/ruby_xml_attr.c +372 -0
- data/ext/xml/ruby_xml_attr.h +21 -0
- data/ext/xml/ruby_xml_attribute.c +224 -0
- data/ext/xml/ruby_xml_attribute.h +21 -0
- data/ext/xml/ruby_xml_document.c +1159 -0
- data/ext/xml/ruby_xml_document.h +27 -0
- data/ext/xml/ruby_xml_dtd.c +168 -0
- data/ext/xml/ruby_xml_dtd.h +17 -0
- data/ext/xml/ruby_xml_input_cbg.c +167 -0
- data/ext/xml/ruby_xml_input_cbg.h +21 -0
- data/ext/xml/ruby_xml_node.c +2052 -0
- data/ext/xml/ruby_xml_node.h +28 -0
- data/ext/xml/ruby_xml_node_set.c +197 -0
- data/ext/xml/ruby_xml_node_set.h +26 -0
- data/ext/xml/ruby_xml_ns.c +153 -0
- data/ext/xml/ruby_xml_ns.h +21 -0
- data/ext/xml/ruby_xml_parser.c +1363 -0
- data/ext/xml/ruby_xml_parser.h +31 -0
- data/ext/xml/ruby_xml_parser_context.c +715 -0
- data/ext/xml/ruby_xml_parser_context.h +22 -0
- data/ext/xml/ruby_xml_sax_parser.c +181 -0
- data/ext/xml/ruby_xml_sax_parser.h +21 -0
- data/ext/xml/ruby_xml_schema.c +142 -0
- data/ext/xml/ruby_xml_schema.h +16 -0
- data/ext/xml/ruby_xml_tree.c +43 -0
- data/ext/xml/ruby_xml_tree.h +12 -0
- data/ext/xml/ruby_xml_xinclude.c +20 -0
- data/ext/xml/ruby_xml_xinclude.h +13 -0
- data/ext/xml/ruby_xml_xpath.c +357 -0
- data/ext/xml/ruby_xml_xpath.h +24 -0
- data/ext/xml/ruby_xml_xpath_context.c +124 -0
- data/ext/xml/ruby_xml_xpath_context.h +24 -0
- data/ext/xml/ruby_xml_xpointer.c +100 -0
- data/ext/xml/ruby_xml_xpointer.h +27 -0
- data/ext/xml/ruby_xml_xpointer_context.c +22 -0
- data/ext/xml/ruby_xml_xpointer_context.h +18 -0
- data/tests/copy_bug.rb +21 -0
- data/tests/dtd-test.rb +24 -0
- data/tests/model/default_validation_bug.rb +0 -0
- data/tests/model/rubynet.xml +78 -0
- data/tests/model/rubynet_project +13 -0
- data/tests/model/xinclude.xml +5 -0
- data/tests/runner.rb +13 -0
- data/tests/schema-test.rb +74 -0
- data/tests/tc_default_validation.rb +0 -0
- data/tests/tc_xml_document.rb +51 -0
- data/tests/tc_xml_document_write.rb +25 -0
- data/tests/tc_xml_document_write2.rb +55 -0
- data/tests/tc_xml_document_write3.rb +97 -0
- data/tests/tc_xml_node.rb +59 -0
- data/tests/tc_xml_node2.rb +26 -0
- data/tests/tc_xml_node_set.rb +25 -0
- data/tests/tc_xml_node_xlink.rb +28 -0
- data/tests/tc_xml_parser.rb +175 -0
- data/tests/tc_xml_parser2.rb +17 -0
- data/tests/tc_xml_parser3.rb +23 -0
- data/tests/tc_xml_parser4.rb +33 -0
- data/tests/tc_xml_parser5.rb +27 -0
- data/tests/tc_xml_parser6.rb +23 -0
- data/tests/tc_xml_parser7.rb +28 -0
- data/tests/tc_xml_parser_context.rb +89 -0
- data/tests/tc_xml_xinclude.rb +30 -0
- data/tests/tc_xml_xpath.rb +23 -0
- data/tests/tc_xml_xpointer.rb +78 -0
- metadata +144 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
/* $Id: ruby_xml_attr.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
|
2
|
+
|
3
|
+
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
+
|
5
|
+
#ifndef __RUBY_XML_ATTR__
|
6
|
+
#define __RUBY_XML_ATTR__
|
7
|
+
|
8
|
+
extern VALUE cXMLAttr;
|
9
|
+
|
10
|
+
typedef struct ruby_xml_attr {
|
11
|
+
xmlAttrPtr attr;
|
12
|
+
VALUE xd;
|
13
|
+
int is_ptr;
|
14
|
+
} ruby_xml_attr;
|
15
|
+
|
16
|
+
void ruby_xml_attr_free(ruby_xml_attr *rxn);
|
17
|
+
void ruby_init_xml_attr(void);
|
18
|
+
VALUE ruby_xml_attr_new(VALUE class, VALUE xd, xmlAttrPtr attr);
|
19
|
+
VALUE ruby_xml_attr_new2(VALUE class, VALUE xd, xmlAttrPtr attr);
|
20
|
+
VALUE ruby_xml_attr_name_get(VALUE self);
|
21
|
+
#endif
|
@@ -0,0 +1,224 @@
|
|
1
|
+
/* $Id: ruby_xml_attribute.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
|
2
|
+
|
3
|
+
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
+
|
5
|
+
#include "libxml.h"
|
6
|
+
#include "ruby_xml_attribute.h"
|
7
|
+
|
8
|
+
VALUE cXMLAttribute;
|
9
|
+
|
10
|
+
// TODO Wtf is this about? It's not referenced outside this file AFAIK...
|
11
|
+
|
12
|
+
VALUE
|
13
|
+
ruby_xml_attribute_child_get(VALUE self) {
|
14
|
+
ruby_xml_attribute *rxa;
|
15
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
16
|
+
if (rxa->attribute->children == NULL)
|
17
|
+
return(Qnil);
|
18
|
+
else
|
19
|
+
return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->children));
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
VALUE
|
24
|
+
ruby_xml_attribute_children_q(VALUE self) {
|
25
|
+
ruby_xml_attribute *rxa;
|
26
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
27
|
+
if (rxa->attribute->children == NULL)
|
28
|
+
return(Qfalse);
|
29
|
+
else
|
30
|
+
return(Qtrue);
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
VALUE
|
35
|
+
ruby_xml_attribute_default_get(VALUE self) {
|
36
|
+
ruby_xml_attribute *rxa;
|
37
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
38
|
+
|
39
|
+
if (rxa->attribute->defaultValue == NULL)
|
40
|
+
return(Qnil);
|
41
|
+
else
|
42
|
+
return(rb_str_new2((const char*)rxa->attribute->defaultValue));
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
VALUE
|
47
|
+
ruby_xml_attribute_element_get(VALUE self) {
|
48
|
+
ruby_xml_attribute *rxa;
|
49
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
50
|
+
|
51
|
+
if (rxa->attribute->elem == NULL)
|
52
|
+
return(Qnil);
|
53
|
+
else
|
54
|
+
return(rb_str_new2((const char*)rxa->attribute->elem));
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
void
|
59
|
+
ruby_xml_attribute_free(ruby_xml_attribute *rxa) {
|
60
|
+
if (rxa->attribute != NULL && !rxa->is_ptr) {
|
61
|
+
xmlUnlinkNode((xmlNodePtr)rxa->attribute);
|
62
|
+
xmlFreeNode((xmlNodePtr)rxa->attribute);
|
63
|
+
rxa->attribute = NULL;
|
64
|
+
}
|
65
|
+
|
66
|
+
free(rxa);
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
VALUE
|
71
|
+
ruby_xml_attribute_last_get(VALUE self) {
|
72
|
+
ruby_xml_attribute *rxa;
|
73
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
74
|
+
if (rxa->attribute->last == NULL)
|
75
|
+
return(Qnil);
|
76
|
+
else
|
77
|
+
return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->last));
|
78
|
+
}
|
79
|
+
|
80
|
+
|
81
|
+
VALUE
|
82
|
+
ruby_xml_attribute_last_q(VALUE self) {
|
83
|
+
ruby_xml_attribute *rxa;
|
84
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
85
|
+
if (rxa->attribute->last == NULL)
|
86
|
+
return(Qfalse);
|
87
|
+
else
|
88
|
+
return(Qtrue);
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
static void
|
93
|
+
ruby_xml_attribute_mark(ruby_xml_attribute *rxa) {
|
94
|
+
if (rxa == NULL) return;
|
95
|
+
if (!NIL_P(rxa->xd)) rb_gc_mark(rxa->xd);
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
VALUE
|
100
|
+
ruby_xml_attribute_name_get(VALUE self) {
|
101
|
+
ruby_xml_attribute *rxa;
|
102
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
103
|
+
|
104
|
+
if (rxa->attribute->name == NULL)
|
105
|
+
return(Qnil);
|
106
|
+
else
|
107
|
+
return(rb_str_new2((const char*)rxa->attribute->name));
|
108
|
+
}
|
109
|
+
|
110
|
+
|
111
|
+
VALUE
|
112
|
+
ruby_xml_attribute_new(VALUE class, VALUE xd, xmlAttributePtr attribute) {
|
113
|
+
ruby_xml_attribute *rxa;
|
114
|
+
|
115
|
+
rxa = ALLOC(ruby_xml_attribute);
|
116
|
+
rxa->is_ptr = 0;
|
117
|
+
rxa->attribute = attribute;
|
118
|
+
if (NIL_P(xd))
|
119
|
+
rxa->xd = Qnil;
|
120
|
+
else
|
121
|
+
rxa->xd = xd;
|
122
|
+
return(Data_Wrap_Struct(class, ruby_xml_attribute_mark,
|
123
|
+
ruby_xml_attribute_free, rxa));
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
VALUE
|
128
|
+
ruby_xml_attribute_new2(VALUE class, VALUE xd, xmlAttributePtr attribute) {
|
129
|
+
ruby_xml_attribute *rxa;
|
130
|
+
|
131
|
+
rxa = ALLOC(ruby_xml_attribute);
|
132
|
+
rxa->is_ptr = 1;
|
133
|
+
rxa->attribute = attribute;
|
134
|
+
if (NIL_P(xd))
|
135
|
+
rxa->xd = Qnil;
|
136
|
+
else
|
137
|
+
rxa->xd = xd;
|
138
|
+
return(Data_Wrap_Struct(class, ruby_xml_attribute_mark,
|
139
|
+
ruby_xml_attribute_free, rxa));
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
VALUE
|
144
|
+
ruby_xml_attribute_next_get(VALUE self) {
|
145
|
+
ruby_xml_attribute *rxa;
|
146
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
147
|
+
if (rxa->attribute->next == NULL)
|
148
|
+
return(Qnil);
|
149
|
+
else
|
150
|
+
return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->next));
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
VALUE
|
155
|
+
ruby_xml_attribute_next_q(VALUE self) {
|
156
|
+
ruby_xml_attribute *rxa;
|
157
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
158
|
+
if (rxa->attribute->next == NULL)
|
159
|
+
return(Qfalse);
|
160
|
+
else
|
161
|
+
return(Qtrue);
|
162
|
+
}
|
163
|
+
|
164
|
+
|
165
|
+
VALUE
|
166
|
+
ruby_xml_attribute_node_type_name(VALUE self) {
|
167
|
+
return(rb_str_new2("attribute"));
|
168
|
+
}
|
169
|
+
|
170
|
+
|
171
|
+
VALUE
|
172
|
+
ruby_xml_attribute_prefix_get(VALUE self) {
|
173
|
+
ruby_xml_attribute *rxa;
|
174
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
175
|
+
|
176
|
+
if (rxa->attribute->prefix == NULL)
|
177
|
+
return(Qnil);
|
178
|
+
else
|
179
|
+
return(rb_str_new2((const char*)rxa->attribute->prefix));
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
VALUE
|
184
|
+
ruby_xml_attribute_prev_get(VALUE self) {
|
185
|
+
ruby_xml_attribute *rxa;
|
186
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
187
|
+
if (rxa->attribute->prev == NULL)
|
188
|
+
return(Qnil);
|
189
|
+
else
|
190
|
+
return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->prev));
|
191
|
+
}
|
192
|
+
|
193
|
+
VALUE
|
194
|
+
ruby_xml_attribute_prev_q(VALUE self) {
|
195
|
+
ruby_xml_attribute *rxa;
|
196
|
+
Data_Get_Struct(self, ruby_xml_attribute, rxa);
|
197
|
+
if (rxa->attribute->prev == NULL)
|
198
|
+
return(Qfalse);
|
199
|
+
else
|
200
|
+
return(Qtrue);
|
201
|
+
}
|
202
|
+
|
203
|
+
// Rdoc maybe doesn't need to know
|
204
|
+
// #ifdef RDOC_NEVER_DEFINED
|
205
|
+
// mXML = rb_define_module("XML");
|
206
|
+
// #endif
|
207
|
+
|
208
|
+
void
|
209
|
+
ruby_init_xml_attribute(void) {
|
210
|
+
cXMLAttribute = rb_define_class_under(mXML, "Attribute", rb_cObject);
|
211
|
+
rb_define_method(cXMLAttribute, "child", ruby_xml_attribute_child_get, 0);
|
212
|
+
rb_define_method(cXMLAttribute, "children?", ruby_xml_attribute_children_q, 0);
|
213
|
+
rb_define_method(cXMLAttribute, "default", ruby_xml_attribute_default_get, 0);
|
214
|
+
rb_define_method(cXMLAttribute, "element", ruby_xml_attribute_element_get, 0);
|
215
|
+
rb_define_method(cXMLAttribute, "last", ruby_xml_attribute_last_get, 0);
|
216
|
+
rb_define_method(cXMLAttribute, "last?", ruby_xml_attribute_last_q, 0);
|
217
|
+
rb_define_method(cXMLAttribute, "node_type_name", ruby_xml_attribute_node_type_name, 0);
|
218
|
+
rb_define_method(cXMLAttribute, "name", ruby_xml_attribute_name_get, 0);
|
219
|
+
rb_define_method(cXMLAttribute, "next", ruby_xml_attribute_next_get, 0);
|
220
|
+
rb_define_method(cXMLAttribute, "next?", ruby_xml_attribute_next_q, 0);
|
221
|
+
rb_define_method(cXMLAttribute, "prefix", ruby_xml_attribute_prefix_get, 0);
|
222
|
+
rb_define_method(cXMLAttribute, "prev", ruby_xml_attribute_prev_get, 0);
|
223
|
+
rb_define_method(cXMLAttribute, "prev?", ruby_xml_attribute_prev_q, 0);
|
224
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/* $Id: ruby_xml_attribute.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
|
2
|
+
|
3
|
+
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
+
|
5
|
+
#ifndef __RUBY_XML_ATTRIBUTE__
|
6
|
+
#define __RUBY_XML_ATTRIBUTE__
|
7
|
+
|
8
|
+
extern VALUE cXMLAttribute;
|
9
|
+
|
10
|
+
typedef struct ruby_xml_attribute {
|
11
|
+
xmlAttributePtr attribute;
|
12
|
+
VALUE xd;
|
13
|
+
int is_ptr;
|
14
|
+
} ruby_xml_attribute;
|
15
|
+
|
16
|
+
void ruby_xml_attribute_free(ruby_xml_attribute *rxa);
|
17
|
+
void ruby_init_xml_attribute(void);
|
18
|
+
VALUE ruby_xml_attribute_new(VALUE class, VALUE xd, xmlAttributePtr attribute);
|
19
|
+
VALUE ruby_xml_attribute_new2(VALUE class, VALUE xd, xmlAttributePtr attribute);
|
20
|
+
VALUE ruby_xml_attribute_name_get(VALUE self);
|
21
|
+
#endif
|
@@ -0,0 +1,1159 @@
|
|
1
|
+
/* $Id: ruby_xml_document.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
|
2
|
+
|
3
|
+
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
+
|
5
|
+
#include "libxml.h"
|
6
|
+
#include "ruby_xml_document.h"
|
7
|
+
|
8
|
+
VALUE cXMLDocument;
|
9
|
+
|
10
|
+
/*
|
11
|
+
* call-seq:
|
12
|
+
* document.compression => num
|
13
|
+
*
|
14
|
+
* Obtain this document's compression mode identifier.
|
15
|
+
*/
|
16
|
+
VALUE
|
17
|
+
ruby_xml_document_compression_get(VALUE self) {
|
18
|
+
#ifdef HAVE_ZLIB_H
|
19
|
+
ruby_xml_document *rxd;
|
20
|
+
int compmode;
|
21
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
22
|
+
|
23
|
+
compmode = xmlGetDocCompressMode(rxd->doc);
|
24
|
+
if (compmode == -1)
|
25
|
+
return(Qnil);
|
26
|
+
else
|
27
|
+
return(INT2NUM(compmode));
|
28
|
+
#else
|
29
|
+
rb_warn("libxml not compiled with zlib support");
|
30
|
+
return(Qfalse);
|
31
|
+
#endif
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
/*
|
36
|
+
* call-seq:
|
37
|
+
* document.compression = num
|
38
|
+
*
|
39
|
+
* Set this document's compression mode.
|
40
|
+
*/
|
41
|
+
VALUE
|
42
|
+
ruby_xml_document_compression_set(VALUE self, VALUE num) {
|
43
|
+
#ifdef HAVE_ZLIB_H
|
44
|
+
ruby_xml_document *rxd;
|
45
|
+
int compmode;
|
46
|
+
Check_Type(num, T_FIXNUM);
|
47
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
48
|
+
|
49
|
+
if (rxd->doc == NULL) {
|
50
|
+
return(Qnil);
|
51
|
+
} else {
|
52
|
+
xmlSetDocCompressMode(rxd->doc, NUM2INT(num));
|
53
|
+
|
54
|
+
compmode = xmlGetDocCompressMode(rxd->doc);
|
55
|
+
if (compmode == -1)
|
56
|
+
return(Qnil);
|
57
|
+
else
|
58
|
+
return(INT2NUM(compmode));
|
59
|
+
}
|
60
|
+
#else
|
61
|
+
rb_warn("libxml compiled without zlib support");
|
62
|
+
return(Qfalse);
|
63
|
+
#endif
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
/*
|
68
|
+
* call-seq:
|
69
|
+
* document.compression? => (true|false)
|
70
|
+
*
|
71
|
+
* Determine whether this document is compressed.
|
72
|
+
*/
|
73
|
+
VALUE
|
74
|
+
ruby_xml_document_compression_q(VALUE self) {
|
75
|
+
#ifdef HAVE_ZLIB_H
|
76
|
+
ruby_xml_document *rxd;
|
77
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
78
|
+
|
79
|
+
if (rxd->doc->compression != -1)
|
80
|
+
return(Qtrue);
|
81
|
+
else
|
82
|
+
return(Qfalse);
|
83
|
+
#else
|
84
|
+
rb_warn("libxml compiled without zlib support");
|
85
|
+
return(Qfalse);
|
86
|
+
#endif
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
/*
|
91
|
+
* call-seq:
|
92
|
+
* document.child => node
|
93
|
+
*
|
94
|
+
* Get this document's child node.
|
95
|
+
*/
|
96
|
+
VALUE
|
97
|
+
ruby_xml_document_child_get(VALUE self) {
|
98
|
+
ruby_xml_document *rxd;
|
99
|
+
ruby_xml_node *rxn;
|
100
|
+
VALUE node;
|
101
|
+
|
102
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
103
|
+
|
104
|
+
if (rxd->doc->children == NULL)
|
105
|
+
return(Qnil);
|
106
|
+
|
107
|
+
node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->children);
|
108
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
109
|
+
rxn->xd = self;
|
110
|
+
return(node);
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
/*
|
115
|
+
* call-seq:
|
116
|
+
* document.child? => (true|false)
|
117
|
+
*
|
118
|
+
* Determine whether this document has a child node.
|
119
|
+
*/
|
120
|
+
VALUE
|
121
|
+
ruby_xml_document_child_q(VALUE self) {
|
122
|
+
ruby_xml_document *rxd;
|
123
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
124
|
+
|
125
|
+
if (rxd->doc->children == NULL)
|
126
|
+
return(Qfalse);
|
127
|
+
else
|
128
|
+
return(Qtrue);
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
/*
|
133
|
+
* call-seq:
|
134
|
+
* document.dump([stream]) => true
|
135
|
+
*
|
136
|
+
* Dump this document's XML to the specified IO stream.
|
137
|
+
* If no stream is specified, stdout is used.
|
138
|
+
*/
|
139
|
+
VALUE
|
140
|
+
ruby_xml_document_dump(int argc, VALUE *argv, VALUE self) {
|
141
|
+
OpenFile *fptr;
|
142
|
+
VALUE io;
|
143
|
+
FILE *out;
|
144
|
+
ruby_xml_document *rxd;
|
145
|
+
|
146
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
147
|
+
if (rxd->doc == NULL)
|
148
|
+
return(Qnil);
|
149
|
+
|
150
|
+
switch (argc) {
|
151
|
+
case 0:
|
152
|
+
io = rb_stdout;
|
153
|
+
break;
|
154
|
+
case 1:
|
155
|
+
io = argv[0];
|
156
|
+
if (!rb_obj_is_kind_of(io, rb_cIO))
|
157
|
+
rb_raise(rb_eTypeError, "need an IO object");
|
158
|
+
break;
|
159
|
+
default:
|
160
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
|
161
|
+
}
|
162
|
+
|
163
|
+
GetOpenFile(io, fptr);
|
164
|
+
rb_io_check_writable(fptr);
|
165
|
+
out = GetWriteFile(fptr);
|
166
|
+
xmlDocDump(out, rxd->doc);
|
167
|
+
return(Qtrue);
|
168
|
+
}
|
169
|
+
|
170
|
+
|
171
|
+
/*
|
172
|
+
* call-seq:
|
173
|
+
* document.debug_dump([stream]) => true
|
174
|
+
*
|
175
|
+
* Debug version of dump.
|
176
|
+
*/
|
177
|
+
VALUE
|
178
|
+
ruby_xml_document_debug_dump(int argc, VALUE *argv, VALUE self) {
|
179
|
+
#ifdef LIBXML_DEBUG_ENABLED
|
180
|
+
OpenFile *fptr;
|
181
|
+
VALUE io;
|
182
|
+
FILE *out;
|
183
|
+
ruby_xml_document *rxd;
|
184
|
+
|
185
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
186
|
+
if (rxd->doc == NULL)
|
187
|
+
return(Qnil);
|
188
|
+
|
189
|
+
switch (argc) {
|
190
|
+
case 0:
|
191
|
+
io = rb_stderr;
|
192
|
+
break;
|
193
|
+
case 1:
|
194
|
+
io = argv[0];
|
195
|
+
if (!rb_obj_is_kind_of(io, rb_cIO))
|
196
|
+
rb_raise(rb_eTypeError, "need an IO object");
|
197
|
+
break;
|
198
|
+
default:
|
199
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
|
200
|
+
}
|
201
|
+
|
202
|
+
GetOpenFile(io, fptr);
|
203
|
+
rb_io_check_writable(fptr);
|
204
|
+
out = GetWriteFile(fptr);
|
205
|
+
xmlDebugDumpDocument(out, rxd->doc);
|
206
|
+
return(Qtrue);
|
207
|
+
#else
|
208
|
+
rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
|
209
|
+
return(Qfalse);
|
210
|
+
#endif
|
211
|
+
}
|
212
|
+
|
213
|
+
|
214
|
+
/*
|
215
|
+
* call-seq:
|
216
|
+
* document.debug_dump_head([stream]) => true
|
217
|
+
*
|
218
|
+
* Debug-dump this document's header to the specified IO stream.
|
219
|
+
* If no stream is specified, stdout is used.
|
220
|
+
*/
|
221
|
+
VALUE
|
222
|
+
ruby_xml_document_debug_dump_head(int argc, VALUE *argv, VALUE self) {
|
223
|
+
#ifdef LIBXML_DEBUG_ENABLED
|
224
|
+
OpenFile *fptr;
|
225
|
+
VALUE io;
|
226
|
+
FILE *out;
|
227
|
+
ruby_xml_document *rxd;
|
228
|
+
|
229
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
230
|
+
if (rxd->doc == NULL)
|
231
|
+
return(Qnil);
|
232
|
+
|
233
|
+
switch (argc) {
|
234
|
+
case 0:
|
235
|
+
io = rb_stdout;
|
236
|
+
break;
|
237
|
+
case 1:
|
238
|
+
io = argv[0];
|
239
|
+
if (!rb_obj_is_kind_of(io, rb_cIO))
|
240
|
+
rb_raise(rb_eTypeError, "need an IO object");
|
241
|
+
break;
|
242
|
+
default:
|
243
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
|
244
|
+
}
|
245
|
+
|
246
|
+
GetOpenFile(io, fptr);
|
247
|
+
rb_io_check_writable(fptr);
|
248
|
+
out = GetWriteFile(fptr);
|
249
|
+
xmlDebugDumpDocumentHead(out, rxd->doc);
|
250
|
+
return(Qtrue);
|
251
|
+
#else
|
252
|
+
rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
|
253
|
+
return(Qfalse);
|
254
|
+
#endif
|
255
|
+
}
|
256
|
+
|
257
|
+
|
258
|
+
/*
|
259
|
+
* call-seq:
|
260
|
+
* document.format_dump([stream], [spacing]) => true
|
261
|
+
*
|
262
|
+
* Dump this document's formatted XML to the specified IO stream.
|
263
|
+
* If no stream is specified, stdout is used. If spacing is
|
264
|
+
* specified, it must be a boolean that determines whether
|
265
|
+
* spacing is used.
|
266
|
+
*/
|
267
|
+
VALUE
|
268
|
+
ruby_xml_document_format_dump(int argc, VALUE *argv, VALUE self) {
|
269
|
+
OpenFile *fptr;
|
270
|
+
VALUE bool, io;
|
271
|
+
FILE *out;
|
272
|
+
ruby_xml_document *rxd;
|
273
|
+
int size, spacing;
|
274
|
+
|
275
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
276
|
+
if (rxd->doc == NULL)
|
277
|
+
return(Qnil);
|
278
|
+
|
279
|
+
switch (argc) {
|
280
|
+
case 0:
|
281
|
+
io = rb_stdout;
|
282
|
+
spacing = 1;
|
283
|
+
break;
|
284
|
+
case 1:
|
285
|
+
io = argv[0];
|
286
|
+
if (!rb_obj_is_kind_of(io, rb_cIO))
|
287
|
+
rb_raise(rb_eTypeError, "need an IO object");
|
288
|
+
spacing = 1;
|
289
|
+
break;
|
290
|
+
case 2:
|
291
|
+
io = argv[0];
|
292
|
+
if (!rb_obj_is_kind_of(io, rb_cIO))
|
293
|
+
rb_raise(rb_eTypeError, "need an IO object");
|
294
|
+
bool = argv[1];
|
295
|
+
if (TYPE(bool) == T_TRUE)
|
296
|
+
spacing = 1;
|
297
|
+
else if (TYPE(bool) == T_FALSE)
|
298
|
+
spacing = 0;
|
299
|
+
else
|
300
|
+
rb_raise(rb_eTypeError, "incorect argument type, second argument must be bool");
|
301
|
+
|
302
|
+
break;
|
303
|
+
default:
|
304
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
|
305
|
+
}
|
306
|
+
|
307
|
+
GetOpenFile(io, fptr);
|
308
|
+
rb_io_check_writable(fptr);
|
309
|
+
out = GetWriteFile(fptr);
|
310
|
+
size = xmlDocFormatDump(out, rxd->doc, spacing);
|
311
|
+
return(INT2NUM(size));
|
312
|
+
}
|
313
|
+
|
314
|
+
|
315
|
+
/*
|
316
|
+
* call-seq:
|
317
|
+
* document.debug_format_dump([stream]) => true
|
318
|
+
*
|
319
|
+
* *Deprecated* in favour of format_dump.
|
320
|
+
*/
|
321
|
+
VALUE
|
322
|
+
ruby_xml_document_debug_format_dump(int argc, VALUE *argv, VALUE self) {
|
323
|
+
rb_warn("debug_format_dump has been deprecaited, use format_dump instead");
|
324
|
+
return(ruby_xml_document_format_dump(argc, argv, self));
|
325
|
+
}
|
326
|
+
|
327
|
+
|
328
|
+
/*
|
329
|
+
* call-seq:
|
330
|
+
* document.encoding => "encoding"
|
331
|
+
*
|
332
|
+
* Obtain the encoding specified by this document.
|
333
|
+
*/
|
334
|
+
VALUE
|
335
|
+
ruby_xml_document_encoding_get(VALUE self) {
|
336
|
+
ruby_xml_document *rxd;
|
337
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
338
|
+
if (rxd->doc->encoding == NULL)
|
339
|
+
return(Qnil);
|
340
|
+
else
|
341
|
+
return(rb_str_new2((const char*)rxd->doc->encoding));
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
/*
|
346
|
+
* call-seq:
|
347
|
+
* document.encoding = "encoding"
|
348
|
+
*
|
349
|
+
* Set the encoding for this document.
|
350
|
+
*/
|
351
|
+
VALUE
|
352
|
+
ruby_xml_document_encoding_set(VALUE self, VALUE encoding) {
|
353
|
+
ruby_xml_document *rxd;
|
354
|
+
|
355
|
+
Check_Type(encoding, T_STRING);
|
356
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
357
|
+
rxd->doc->encoding = (xmlChar*)ruby_strdup(StringValuePtr(encoding));
|
358
|
+
return(ruby_xml_document_encoding_get(self));
|
359
|
+
}
|
360
|
+
|
361
|
+
|
362
|
+
/*
|
363
|
+
* call-seq:
|
364
|
+
* document.filename => "filename"
|
365
|
+
*
|
366
|
+
* Obtain the filename this document was read from.
|
367
|
+
*/
|
368
|
+
VALUE
|
369
|
+
ruby_xml_document_filename_get(VALUE self) {
|
370
|
+
ruby_xml_document *rxd;
|
371
|
+
rx_file_data *data;
|
372
|
+
|
373
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
374
|
+
if (rxd->data == NULL)
|
375
|
+
return(Qnil);
|
376
|
+
|
377
|
+
switch (rxd->data_type) {
|
378
|
+
case RUBY_LIBXML_SRC_TYPE_NULL:
|
379
|
+
return(Qnil);
|
380
|
+
case RUBY_LIBXML_SRC_TYPE_FILE:
|
381
|
+
data = (rx_file_data *)rxd->data;
|
382
|
+
return(data->filename);
|
383
|
+
default:
|
384
|
+
rb_fatal("Unknown document type in libxml");
|
385
|
+
}
|
386
|
+
|
387
|
+
return(Qnil);
|
388
|
+
}
|
389
|
+
|
390
|
+
|
391
|
+
/*
|
392
|
+
* call-seq:
|
393
|
+
* document.find(xpath_expr, [namespace]) => nodeset
|
394
|
+
*
|
395
|
+
* Find nodes matching the specified xpath expression, optionally
|
396
|
+
* using the specified namespace. Returns an XML::Node::Set.
|
397
|
+
*/
|
398
|
+
VALUE
|
399
|
+
ruby_xml_document_find(int argc, VALUE *argv, VALUE self) {
|
400
|
+
int i, vargc;
|
401
|
+
VALUE *vargv;
|
402
|
+
|
403
|
+
if (argc > 2 || argc < 1)
|
404
|
+
rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
|
405
|
+
|
406
|
+
vargc = argc + 1;
|
407
|
+
vargv = ALLOC_N(VALUE, vargc + 1);
|
408
|
+
vargv[0] = ruby_xml_document_root_get(self);
|
409
|
+
for (i = 0; i<argc; i++)
|
410
|
+
vargv[i + 1] = argv[i];
|
411
|
+
|
412
|
+
return(ruby_xml_xpath_find2(vargc, vargv));
|
413
|
+
}
|
414
|
+
|
415
|
+
|
416
|
+
void
|
417
|
+
ruby_xml_document_free(ruby_xml_document *rxd) {
|
418
|
+
void *data;
|
419
|
+
|
420
|
+
if (rxd->doc != NULL && !rxd->is_ptr) {
|
421
|
+
xmlFreeDoc(rxd->doc);
|
422
|
+
ruby_xml_parser_count--;
|
423
|
+
rxd->doc = NULL;
|
424
|
+
}
|
425
|
+
|
426
|
+
if (ruby_xml_parser_count == 0)
|
427
|
+
xmlCleanupParser();
|
428
|
+
|
429
|
+
switch(rxd->data_type) {
|
430
|
+
case RUBY_LIBXML_SRC_TYPE_NULL:
|
431
|
+
break;
|
432
|
+
case RUBY_LIBXML_SRC_TYPE_FILE:
|
433
|
+
data = (void*)(rx_file_data *)rxd->data;
|
434
|
+
free((rx_file_data *)data);
|
435
|
+
break;
|
436
|
+
case RUBY_LIBXML_SRC_TYPE_STRING:
|
437
|
+
data = (void*)(rx_string_data *)rxd->data;
|
438
|
+
free((rx_string_data *)data);
|
439
|
+
break;
|
440
|
+
case RUBY_LIBXML_SRC_TYPE_IO:
|
441
|
+
data = (void*)(rx_io_data *)rxd->data;
|
442
|
+
free((rx_io_data *)data);
|
443
|
+
break;
|
444
|
+
default:
|
445
|
+
rb_fatal("Unknown data type, %d", rxd->data_type);
|
446
|
+
}
|
447
|
+
|
448
|
+
free(rxd);
|
449
|
+
}
|
450
|
+
|
451
|
+
|
452
|
+
/*
|
453
|
+
* call-seq:
|
454
|
+
* XML::Document.new(xml_version = 1.0) => document
|
455
|
+
*
|
456
|
+
* Create a new XML::Document, optionally specifying the
|
457
|
+
* XML version.
|
458
|
+
*/
|
459
|
+
VALUE
|
460
|
+
ruby_xml_document_initialize(int argc, VALUE *argv, VALUE class) {
|
461
|
+
VALUE docobj, xmlver;
|
462
|
+
|
463
|
+
switch (argc) {
|
464
|
+
case 0:
|
465
|
+
xmlver = rb_str_new2("1.0");
|
466
|
+
break;
|
467
|
+
case 1:
|
468
|
+
rb_scan_args(argc, argv, "01", &xmlver);
|
469
|
+
break;
|
470
|
+
default:
|
471
|
+
rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
|
472
|
+
}
|
473
|
+
|
474
|
+
docobj = ruby_xml_document_new2(cXMLDocument, xmlver);
|
475
|
+
return(docobj);
|
476
|
+
}
|
477
|
+
|
478
|
+
|
479
|
+
/*
|
480
|
+
* call-seq:
|
481
|
+
* document.last => node
|
482
|
+
*
|
483
|
+
* Obtain the last node.
|
484
|
+
*/
|
485
|
+
VALUE
|
486
|
+
ruby_xml_document_last_get(VALUE self) {
|
487
|
+
ruby_xml_document *rxd;
|
488
|
+
ruby_xml_node *rxn;
|
489
|
+
VALUE node;
|
490
|
+
|
491
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
492
|
+
|
493
|
+
if (rxd->doc->last == NULL)
|
494
|
+
return(Qnil);
|
495
|
+
|
496
|
+
node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->last);
|
497
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
498
|
+
rxn->xd = self;
|
499
|
+
return(node);
|
500
|
+
}
|
501
|
+
|
502
|
+
|
503
|
+
/*
|
504
|
+
* call-seq:
|
505
|
+
* document.last? => (true|false)
|
506
|
+
*
|
507
|
+
* Determine whether there is a last node.
|
508
|
+
*/
|
509
|
+
VALUE
|
510
|
+
ruby_xml_document_last_q(VALUE self) {
|
511
|
+
ruby_xml_document *rxd;
|
512
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
513
|
+
|
514
|
+
if (rxd->doc->last == NULL)
|
515
|
+
return(Qfalse);
|
516
|
+
else
|
517
|
+
return(Qtrue);
|
518
|
+
}
|
519
|
+
|
520
|
+
|
521
|
+
static void
|
522
|
+
ruby_xml_document_mark(ruby_xml_document *rxd) {
|
523
|
+
if (rxd == NULL) return;
|
524
|
+
if (!NIL_P(rxd->xmlver)) rb_gc_mark(rxd->xmlver);
|
525
|
+
}
|
526
|
+
|
527
|
+
|
528
|
+
VALUE
|
529
|
+
ruby_xml_document_new(VALUE class, xmlDocPtr doc) {
|
530
|
+
ruby_xml_document *rxd;
|
531
|
+
|
532
|
+
rxd = ALLOC(ruby_xml_document);
|
533
|
+
ruby_xml_parser_count++;
|
534
|
+
|
535
|
+
rxd->data = NULL;
|
536
|
+
rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
|
537
|
+
rxd->doc = doc;
|
538
|
+
rxd->is_ptr = 0;
|
539
|
+
rxd->xmlver = Qnil;
|
540
|
+
|
541
|
+
return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
|
542
|
+
ruby_xml_document_free, rxd));
|
543
|
+
}
|
544
|
+
|
545
|
+
|
546
|
+
VALUE
|
547
|
+
ruby_xml_document_new2(VALUE class, VALUE xmlver) {
|
548
|
+
ruby_xml_document *rxd;
|
549
|
+
|
550
|
+
Check_Type(xmlver, T_STRING);
|
551
|
+
rxd = ALLOC(ruby_xml_document);
|
552
|
+
ruby_xml_parser_count++;
|
553
|
+
|
554
|
+
rxd->data = NULL;
|
555
|
+
rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
|
556
|
+
rxd->doc = xmlNewDoc((xmlChar*)StringValuePtr(xmlver));
|
557
|
+
rxd->is_ptr = 0;
|
558
|
+
rxd->xmlver = xmlver;
|
559
|
+
|
560
|
+
if (rxd->doc == NULL)
|
561
|
+
rb_fatal("bad");
|
562
|
+
|
563
|
+
return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
|
564
|
+
ruby_xml_document_free, rxd));
|
565
|
+
}
|
566
|
+
|
567
|
+
|
568
|
+
VALUE
|
569
|
+
ruby_xml_document_new3(VALUE class) {
|
570
|
+
return(ruby_xml_document_new2(class, rb_str_new2("1.0")));
|
571
|
+
}
|
572
|
+
|
573
|
+
|
574
|
+
VALUE
|
575
|
+
ruby_xml_document_new4(VALUE class, xmlDocPtr doc) {
|
576
|
+
ruby_xml_document *rxd;
|
577
|
+
|
578
|
+
rxd = ALLOC(ruby_xml_document);
|
579
|
+
|
580
|
+
rxd->data = NULL;
|
581
|
+
rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
|
582
|
+
rxd->doc = doc;
|
583
|
+
rxd->is_ptr = 1;
|
584
|
+
rxd->xmlver = Qnil;
|
585
|
+
|
586
|
+
return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
|
587
|
+
ruby_xml_document_free, rxd));
|
588
|
+
}
|
589
|
+
|
590
|
+
|
591
|
+
/*
|
592
|
+
* call-seq:
|
593
|
+
* XML::Document.file(filename) => document
|
594
|
+
*
|
595
|
+
* Create a new XML::Document by parsing the specified
|
596
|
+
* file.
|
597
|
+
*/
|
598
|
+
VALUE
|
599
|
+
ruby_xml_document_new_file(VALUE class, VALUE filename) {
|
600
|
+
VALUE parser;
|
601
|
+
|
602
|
+
parser = ruby_xml_parser_new(cXMLParser);
|
603
|
+
ruby_xml_parser_filename_set(parser, filename);
|
604
|
+
return(ruby_xml_parser_parse(parser));
|
605
|
+
}
|
606
|
+
|
607
|
+
|
608
|
+
/*
|
609
|
+
* call-seq:
|
610
|
+
* document.next => node
|
611
|
+
*
|
612
|
+
* Obtain the next node.
|
613
|
+
*/
|
614
|
+
VALUE
|
615
|
+
ruby_xml_document_next_get(VALUE self) {
|
616
|
+
ruby_xml_document *rxd;
|
617
|
+
ruby_xml_node *rxn;
|
618
|
+
VALUE node;
|
619
|
+
|
620
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
621
|
+
|
622
|
+
if (rxd->doc->next == NULL)
|
623
|
+
return(Qnil);
|
624
|
+
|
625
|
+
node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->next);
|
626
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
627
|
+
rxn->xd = self;
|
628
|
+
return(node);
|
629
|
+
}
|
630
|
+
|
631
|
+
|
632
|
+
/*
|
633
|
+
* call-seq:
|
634
|
+
* document.next? => (true|false)
|
635
|
+
*
|
636
|
+
* Determine whether there is a next node.
|
637
|
+
*/
|
638
|
+
VALUE
|
639
|
+
ruby_xml_document_next_q(VALUE self) {
|
640
|
+
ruby_xml_document *rxd;
|
641
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
642
|
+
|
643
|
+
if (rxd->doc->next == NULL)
|
644
|
+
return(Qfalse);
|
645
|
+
else
|
646
|
+
return(Qtrue);
|
647
|
+
}
|
648
|
+
|
649
|
+
|
650
|
+
/*
|
651
|
+
* call-seq:
|
652
|
+
* document.parent => node
|
653
|
+
*
|
654
|
+
* Obtain the parent node.
|
655
|
+
*/
|
656
|
+
VALUE
|
657
|
+
ruby_xml_document_parent_get(VALUE self) {
|
658
|
+
ruby_xml_document *rxd;
|
659
|
+
ruby_xml_node *rxn;
|
660
|
+
VALUE node;
|
661
|
+
|
662
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
663
|
+
|
664
|
+
if (rxd->doc->parent == NULL)
|
665
|
+
return(Qnil);
|
666
|
+
|
667
|
+
node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->parent);
|
668
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
669
|
+
rxn->xd = self;
|
670
|
+
return(node);
|
671
|
+
}
|
672
|
+
|
673
|
+
|
674
|
+
/*
|
675
|
+
* call-seq:
|
676
|
+
* document.parent? => (true|false)
|
677
|
+
*
|
678
|
+
* Determine whether there is a parent node.
|
679
|
+
*/
|
680
|
+
VALUE
|
681
|
+
ruby_xml_document_parent_q(VALUE self) {
|
682
|
+
ruby_xml_document *rxd;
|
683
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
684
|
+
|
685
|
+
if (rxd->doc->parent == NULL)
|
686
|
+
return(Qfalse);
|
687
|
+
else
|
688
|
+
return(Qtrue);
|
689
|
+
}
|
690
|
+
|
691
|
+
|
692
|
+
/*
|
693
|
+
* call-seq:
|
694
|
+
* document.prev => node
|
695
|
+
*
|
696
|
+
* Obtain the previous node.
|
697
|
+
*/
|
698
|
+
VALUE
|
699
|
+
ruby_xml_document_prev_get(VALUE self) {
|
700
|
+
ruby_xml_document *rxd;
|
701
|
+
ruby_xml_node *rxn;
|
702
|
+
VALUE node;
|
703
|
+
|
704
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
705
|
+
|
706
|
+
if (rxd->doc->prev == NULL)
|
707
|
+
return(Qnil);
|
708
|
+
|
709
|
+
node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->prev);
|
710
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
711
|
+
rxn->xd = self;
|
712
|
+
return(node);
|
713
|
+
}
|
714
|
+
|
715
|
+
|
716
|
+
/*
|
717
|
+
* call-seq:
|
718
|
+
* document.prev? => (true|false)
|
719
|
+
*
|
720
|
+
* Determine whether there is a previous node.
|
721
|
+
*/
|
722
|
+
VALUE
|
723
|
+
ruby_xml_document_prev_q(VALUE self) {
|
724
|
+
ruby_xml_document *rxd;
|
725
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
726
|
+
|
727
|
+
if (rxd->doc->prev == NULL)
|
728
|
+
return(Qfalse);
|
729
|
+
else
|
730
|
+
return(Qtrue);
|
731
|
+
}
|
732
|
+
|
733
|
+
|
734
|
+
/*
|
735
|
+
* call-seq:
|
736
|
+
* document["key"] => "value"
|
737
|
+
*
|
738
|
+
* Obtain the named property.
|
739
|
+
*/
|
740
|
+
VALUE
|
741
|
+
ruby_xml_document_property_get(VALUE self, VALUE key) {
|
742
|
+
return(ruby_xml_node_property_get(ruby_xml_document_root_get(self), key));
|
743
|
+
}
|
744
|
+
|
745
|
+
|
746
|
+
/*
|
747
|
+
* call-seq:
|
748
|
+
* document["key"] = "value"
|
749
|
+
*
|
750
|
+
* Set the named property.
|
751
|
+
*/
|
752
|
+
VALUE
|
753
|
+
ruby_xml_document_property_set(VALUE self, VALUE key, VALUE val) {
|
754
|
+
return(ruby_xml_node_property_set(ruby_xml_document_root_get(self), key, val));
|
755
|
+
}
|
756
|
+
|
757
|
+
|
758
|
+
/*
|
759
|
+
* call-seq:
|
760
|
+
* document.root => node
|
761
|
+
*
|
762
|
+
* Obtain the root node.
|
763
|
+
*/
|
764
|
+
VALUE
|
765
|
+
ruby_xml_document_root_get(VALUE self) {
|
766
|
+
ruby_xml_document *rxd;
|
767
|
+
ruby_xml_node *rxn;
|
768
|
+
VALUE node;
|
769
|
+
xmlNodePtr root;
|
770
|
+
|
771
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
772
|
+
root = xmlDocGetRootElement(rxd->doc);
|
773
|
+
|
774
|
+
if (root == NULL)
|
775
|
+
return(Qnil);
|
776
|
+
|
777
|
+
node = ruby_xml_node_new2(cXMLNode, self, root);
|
778
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
779
|
+
rxn->xd = self;
|
780
|
+
return(node);
|
781
|
+
}
|
782
|
+
|
783
|
+
|
784
|
+
/*
|
785
|
+
* call-seq:
|
786
|
+
* document.root = node
|
787
|
+
*
|
788
|
+
* Set the root node.
|
789
|
+
*/
|
790
|
+
VALUE
|
791
|
+
ruby_xml_document_root_set(VALUE self, VALUE node) {
|
792
|
+
ruby_xml_document *rxd;
|
793
|
+
ruby_xml_node *rxn;
|
794
|
+
VALUE retnode;
|
795
|
+
xmlNodePtr root;
|
796
|
+
|
797
|
+
if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
|
798
|
+
rb_raise(rb_eTypeError, "must pass an XML::Node type object");
|
799
|
+
|
800
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
801
|
+
Data_Get_Struct(node, ruby_xml_node, rxn);
|
802
|
+
ruby_xml_node_set_ptr(node, 1);
|
803
|
+
root = xmlDocSetRootElement(rxd->doc, rxn->node);
|
804
|
+
if (root == NULL)
|
805
|
+
return(Qnil);
|
806
|
+
|
807
|
+
retnode = ruby_xml_node_new2(cXMLNode, self, root);
|
808
|
+
return(retnode);
|
809
|
+
}
|
810
|
+
|
811
|
+
|
812
|
+
/*
|
813
|
+
* call-seq:
|
814
|
+
* document.save(format = false)
|
815
|
+
*
|
816
|
+
* Save this document to the file given by filename,
|
817
|
+
* optionally formatting the output.
|
818
|
+
*/
|
819
|
+
VALUE
|
820
|
+
ruby_xml_document_save(int argc, VALUE *argv, VALUE self) {
|
821
|
+
ruby_xml_document *rxd;
|
822
|
+
const char *filename;
|
823
|
+
int format, len;
|
824
|
+
|
825
|
+
format = 0;
|
826
|
+
switch (argc) {
|
827
|
+
case 1:
|
828
|
+
break;
|
829
|
+
case 2:
|
830
|
+
if (TYPE(argv[1]) == T_TRUE)
|
831
|
+
format = 1;
|
832
|
+
else if (TYPE(argv[1]) == T_FALSE)
|
833
|
+
format = 0;
|
834
|
+
else
|
835
|
+
rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
|
836
|
+
break;
|
837
|
+
default:
|
838
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
|
839
|
+
}
|
840
|
+
|
841
|
+
Check_Type(argv[0], T_STRING);
|
842
|
+
filename = StringValuePtr(argv[0]);
|
843
|
+
|
844
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
845
|
+
len = xmlSaveFormatFileEnc(filename, rxd->doc, (const char*)rxd->doc->encoding, format);
|
846
|
+
if (len == -1)
|
847
|
+
rb_fatal("Unable to write out file");
|
848
|
+
else
|
849
|
+
return(INT2NUM(len));
|
850
|
+
}
|
851
|
+
|
852
|
+
|
853
|
+
/*
|
854
|
+
* call-seq:
|
855
|
+
* document.standalone? => (true|false)
|
856
|
+
*
|
857
|
+
* Determine whether this is a standalone document.
|
858
|
+
*/
|
859
|
+
VALUE
|
860
|
+
ruby_xml_document_standalone_q(VALUE self) {
|
861
|
+
ruby_xml_document *rxd;
|
862
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
863
|
+
if (rxd->doc->standalone)
|
864
|
+
return(Qtrue);
|
865
|
+
else
|
866
|
+
return(Qfalse);
|
867
|
+
}
|
868
|
+
|
869
|
+
|
870
|
+
/*
|
871
|
+
* call-seq:
|
872
|
+
* document.to_s => "xml"
|
873
|
+
*
|
874
|
+
* Coerce this document to a string representation
|
875
|
+
* of it's XML.
|
876
|
+
*/
|
877
|
+
VALUE
|
878
|
+
ruby_xml_document_to_s(int argc, VALUE *argv, VALUE self) {
|
879
|
+
ruby_xml_document *rxd;
|
880
|
+
xmlChar *result;
|
881
|
+
int format, len;
|
882
|
+
|
883
|
+
switch (argc) {
|
884
|
+
case 0:
|
885
|
+
format = 1;
|
886
|
+
break;
|
887
|
+
case 1:
|
888
|
+
if (TYPE(argv[0]) == T_TRUE)
|
889
|
+
format = 1;
|
890
|
+
else if (TYPE(argv[0]) == T_FALSE)
|
891
|
+
format = 0;
|
892
|
+
else
|
893
|
+
rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
|
894
|
+
break;
|
895
|
+
default:
|
896
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
|
897
|
+
}
|
898
|
+
|
899
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
900
|
+
if (rxd->doc == NULL) {
|
901
|
+
return(Qnil);
|
902
|
+
} else if (rxd->doc->encoding != NULL) {
|
903
|
+
if (format) {
|
904
|
+
xmlDocDumpFormatMemoryEnc(rxd->doc, &result, &len,
|
905
|
+
(const char*)rxd->doc->encoding, format);
|
906
|
+
} else {
|
907
|
+
xmlDocDumpMemoryEnc(rxd->doc, &result, &len,
|
908
|
+
(const char*)rxd->doc->encoding);
|
909
|
+
}
|
910
|
+
} else {
|
911
|
+
if (format)
|
912
|
+
xmlDocDumpFormatMemory(rxd->doc, &result, &len, format);
|
913
|
+
else
|
914
|
+
xmlDocDumpMemory(rxd->doc, &result, &len);
|
915
|
+
}
|
916
|
+
|
917
|
+
return(rb_str_new2((const char*)result));
|
918
|
+
}
|
919
|
+
|
920
|
+
|
921
|
+
/*
|
922
|
+
* call-seq:
|
923
|
+
* document.url => "url"
|
924
|
+
*
|
925
|
+
* Obtain this document's source URL, if any.
|
926
|
+
*/
|
927
|
+
VALUE
|
928
|
+
ruby_xml_document_url_get(VALUE self) {
|
929
|
+
ruby_xml_document *rxd;
|
930
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
931
|
+
if (rxd->doc->URL == NULL)
|
932
|
+
return(Qnil);
|
933
|
+
else
|
934
|
+
return(rb_str_new2((const char*)rxd->doc->URL));
|
935
|
+
}
|
936
|
+
|
937
|
+
|
938
|
+
/*
|
939
|
+
* call-seq:
|
940
|
+
* document.version => "version"
|
941
|
+
*
|
942
|
+
* Obtain the XML version specified by this document.
|
943
|
+
*/
|
944
|
+
VALUE
|
945
|
+
ruby_xml_document_version_get(VALUE self) {
|
946
|
+
ruby_xml_document *rxd;
|
947
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
948
|
+
if (rxd->doc->version == NULL)
|
949
|
+
return(Qnil);
|
950
|
+
else
|
951
|
+
return(rb_str_new2((const char*)rxd->doc->version));
|
952
|
+
}
|
953
|
+
|
954
|
+
|
955
|
+
/*
|
956
|
+
* call-seq:
|
957
|
+
* document.xinclude => num
|
958
|
+
*
|
959
|
+
* Process xinclude directives in this document.
|
960
|
+
*/
|
961
|
+
VALUE
|
962
|
+
ruby_xml_document_xinclude(VALUE self) {
|
963
|
+
#ifdef LIBXML_XINCLUDE_ENABLED
|
964
|
+
ruby_xml_document *rxd;
|
965
|
+
int ret;
|
966
|
+
|
967
|
+
Data_Get_Struct(self, ruby_xml_document, rxd);
|
968
|
+
ret = xmlXIncludeProcess(rxd->doc);
|
969
|
+
if (ret >= 0)
|
970
|
+
return(INT2NUM(ret));
|
971
|
+
else
|
972
|
+
rb_raise(eXMLXIncludeError, "error processing xinclude directives in document");
|
973
|
+
#else
|
974
|
+
rb_warn("libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
|
975
|
+
return(Qfalse);
|
976
|
+
#endif
|
977
|
+
}
|
978
|
+
|
979
|
+
void
|
980
|
+
LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
|
981
|
+
{
|
982
|
+
if (rb_block_given_p()) {
|
983
|
+
char buff[1024];
|
984
|
+
snprintf(buff, 1024, msg, ap);
|
985
|
+
rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
|
986
|
+
} else {
|
987
|
+
fprintf(stderr, "error -- found validity error: ");
|
988
|
+
fprintf(stderr, msg, ap);
|
989
|
+
}
|
990
|
+
}
|
991
|
+
|
992
|
+
void
|
993
|
+
LibXML_validity_warning(void * ctxt, const char * msg, va_list ap)
|
994
|
+
{
|
995
|
+
if (rb_block_given_p()) {
|
996
|
+
char buff[1024];
|
997
|
+
snprintf(buff, 1024, msg, ap);
|
998
|
+
rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qfalse));
|
999
|
+
} else {
|
1000
|
+
fprintf(stderr, "warning -- found validity error: ");
|
1001
|
+
fprintf(stderr, msg, ap);
|
1002
|
+
}
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
/*
|
1006
|
+
* call-seq:
|
1007
|
+
* document.validate(schema) => (true|false)
|
1008
|
+
*
|
1009
|
+
* Validate this document against the specified XML::Schema.
|
1010
|
+
*/
|
1011
|
+
VALUE
|
1012
|
+
ruby_xml_document_validate_schema(VALUE self, VALUE schema) {
|
1013
|
+
xmlSchemaValidCtxtPtr vptr;
|
1014
|
+
ruby_xml_document *c_doc;
|
1015
|
+
ruby_xml_schema *c_schema;
|
1016
|
+
int is_invalid;
|
1017
|
+
|
1018
|
+
Data_Get_Struct(self, ruby_xml_document, c_doc);
|
1019
|
+
Data_Get_Struct(schema, ruby_xml_schema, c_schema);
|
1020
|
+
|
1021
|
+
vptr = xmlSchemaNewValidCtxt(c_schema->schema);
|
1022
|
+
|
1023
|
+
xmlSchemaSetValidErrors(vptr, (xmlSchemaValidityErrorFunc)LibXML_validity_error,
|
1024
|
+
(xmlSchemaValidityWarningFunc)LibXML_validity_warning, NULL);
|
1025
|
+
|
1026
|
+
is_invalid = xmlSchemaValidateDoc(vptr, c_doc->doc);
|
1027
|
+
xmlSchemaFreeValidCtxt(vptr);
|
1028
|
+
if (is_invalid) {
|
1029
|
+
return Qfalse;
|
1030
|
+
} else {
|
1031
|
+
return Qtrue;
|
1032
|
+
}
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
|
1036
|
+
/*
|
1037
|
+
* call-seq:
|
1038
|
+
* document.validate(schema) => (true|false)
|
1039
|
+
*
|
1040
|
+
* Validate this document against the specified XML::DTD.
|
1041
|
+
*/
|
1042
|
+
VALUE
|
1043
|
+
ruby_xml_document_validate_dtd(VALUE self, VALUE dtd) {
|
1044
|
+
xmlValidCtxt cvp;
|
1045
|
+
ruby_xml_document *c_doc;
|
1046
|
+
ruby_xml_dtd *c_dtd;
|
1047
|
+
|
1048
|
+
Data_Get_Struct(self, ruby_xml_document, c_doc);
|
1049
|
+
Data_Get_Struct(dtd, ruby_xml_dtd, c_dtd);
|
1050
|
+
|
1051
|
+
cvp.userData = NULL;
|
1052
|
+
cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
|
1053
|
+
cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
|
1054
|
+
|
1055
|
+
cvp.nodeNr = 0;
|
1056
|
+
cvp.nodeTab = NULL;
|
1057
|
+
cvp.vstateNr = 0;
|
1058
|
+
cvp.vstateTab = NULL;
|
1059
|
+
|
1060
|
+
if ( xmlValidateDtd(&cvp, c_doc->doc, c_dtd->dtd) )
|
1061
|
+
return(Qtrue);
|
1062
|
+
else
|
1063
|
+
return(Qfalse);
|
1064
|
+
|
1065
|
+
// int xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd)
|
1066
|
+
/*
|
1067
|
+
int
|
1068
|
+
validate(self, ...)
|
1069
|
+
xmlDocPtr self
|
1070
|
+
PREINIT:
|
1071
|
+
xmlValidCtxt cvp;
|
1072
|
+
xmlDtdPtr dtd;
|
1073
|
+
SV * dtd_sv;
|
1074
|
+
STRLEN n_a, len;
|
1075
|
+
CODE:
|
1076
|
+
LibXML_init_error();
|
1077
|
+
cvp.userData = (void*)PerlIO_stderr();
|
1078
|
+
cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
|
1079
|
+
cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
|
1080
|
+
// we need to initialize the node stack, because perl might
|
1081
|
+
// already messed it up.
|
1082
|
+
//
|
1083
|
+
cvp.nodeNr = 0;
|
1084
|
+
cvp.nodeTab = NULL;
|
1085
|
+
cvp.vstateNr = 0;
|
1086
|
+
cvp.vstateTab = NULL;
|
1087
|
+
|
1088
|
+
if (items > 1) {
|
1089
|
+
dtd_sv = ST(1);
|
1090
|
+
if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
|
1091
|
+
dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
|
1092
|
+
}
|
1093
|
+
else {
|
1094
|
+
croak("is_valid: argument must be a DTD object");
|
1095
|
+
}
|
1096
|
+
RETVAL = xmlValidateDtd(&cvp, self , dtd);
|
1097
|
+
}
|
1098
|
+
else {
|
1099
|
+
RETVAL = xmlValidateDocument(&cvp, self);
|
1100
|
+
}
|
1101
|
+
sv_2mortal(LibXML_error);
|
1102
|
+
|
1103
|
+
if (RETVAL == 0) {
|
1104
|
+
LibXML_croak_error();
|
1105
|
+
}
|
1106
|
+
OUTPUT:
|
1107
|
+
RETVAL
|
1108
|
+
*/
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
// Rdoc needs to know
|
1112
|
+
#ifdef RDOC_NEVER_DEFINED
|
1113
|
+
mXML = rb_define_module("XML");
|
1114
|
+
#endif
|
1115
|
+
|
1116
|
+
void
|
1117
|
+
ruby_init_xml_document(void) {
|
1118
|
+
cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
|
1119
|
+
rb_define_singleton_method(cXMLDocument, "file", ruby_xml_document_new_file, 1);
|
1120
|
+
rb_define_singleton_method(cXMLDocument, "new", ruby_xml_document_initialize, -1);
|
1121
|
+
|
1122
|
+
//rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
|
1123
|
+
//eDTDValidityWarning = rb_define_class_under(cXMLNode, "ValidityWarning", rb_eException);
|
1124
|
+
//eDTDValidityError = rb_define_class_under(cXMLNode, "ValidityWarning", rb_eException);
|
1125
|
+
rb_define_method(cXMLDocument, "[]", ruby_xml_document_property_get, 1);
|
1126
|
+
rb_define_method(cXMLDocument, "[]=", ruby_xml_document_property_set, 2);
|
1127
|
+
rb_define_method(cXMLDocument, "child", ruby_xml_document_child_get, 0);
|
1128
|
+
rb_define_method(cXMLDocument, "child?", ruby_xml_document_child_q, 0);
|
1129
|
+
rb_define_method(cXMLDocument, "compression", ruby_xml_document_compression_get, 0);
|
1130
|
+
rb_define_method(cXMLDocument, "compression=", ruby_xml_document_compression_set, 1);
|
1131
|
+
rb_define_method(cXMLDocument, "compression?", ruby_xml_document_compression_q, 0);
|
1132
|
+
rb_define_method(cXMLDocument, "dump", ruby_xml_document_dump, -1);
|
1133
|
+
rb_define_method(cXMLDocument, "debug_dump", ruby_xml_document_debug_dump, -1);
|
1134
|
+
rb_define_method(cXMLDocument, "debug_dump_head", ruby_xml_document_debug_dump_head, -1);
|
1135
|
+
rb_define_method(cXMLDocument, "debug_format_dump", ruby_xml_document_debug_format_dump, -1);
|
1136
|
+
rb_define_method(cXMLDocument, "encoding", ruby_xml_document_encoding_get, 0);
|
1137
|
+
rb_define_method(cXMLDocument, "encoding=", ruby_xml_document_encoding_set, 1);
|
1138
|
+
rb_define_method(cXMLDocument, "filename", ruby_xml_document_filename_get, 0);
|
1139
|
+
rb_define_method(cXMLDocument, "find", ruby_xml_document_find, -1);
|
1140
|
+
rb_define_method(cXMLDocument, "format_dump", ruby_xml_document_format_dump, -1);
|
1141
|
+
rb_define_method(cXMLDocument, "last", ruby_xml_document_last_get, 0);
|
1142
|
+
rb_define_method(cXMLDocument, "last?", ruby_xml_document_last_q, 0);
|
1143
|
+
rb_define_method(cXMLDocument, "next", ruby_xml_document_next_get, 0);
|
1144
|
+
rb_define_method(cXMLDocument, "next?", ruby_xml_document_next_q, 0);
|
1145
|
+
rb_define_method(cXMLDocument, "parent", ruby_xml_document_parent_get, 0);
|
1146
|
+
rb_define_method(cXMLDocument, "parent?", ruby_xml_document_parent_q, 0);
|
1147
|
+
rb_define_method(cXMLDocument, "prev", ruby_xml_document_prev_get, 0);
|
1148
|
+
rb_define_method(cXMLDocument, "prev?", ruby_xml_document_prev_q, 0);
|
1149
|
+
rb_define_method(cXMLDocument, "root", ruby_xml_document_root_get, 0);
|
1150
|
+
rb_define_method(cXMLDocument, "root=", ruby_xml_document_root_set, 1);
|
1151
|
+
rb_define_method(cXMLDocument, "save", ruby_xml_document_save, -1);
|
1152
|
+
rb_define_method(cXMLDocument, "standalone?", ruby_xml_document_standalone_q, 0);
|
1153
|
+
rb_define_method(cXMLDocument, "to_s", ruby_xml_document_to_s, -1);
|
1154
|
+
rb_define_method(cXMLDocument, "url", ruby_xml_document_url_get, 0);
|
1155
|
+
rb_define_method(cXMLDocument, "version", ruby_xml_document_version_get, 0);
|
1156
|
+
rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
|
1157
|
+
rb_define_method(cXMLDocument, "validate", ruby_xml_document_validate_dtd, 1);
|
1158
|
+
rb_define_method(cXMLDocument, "validate_schema", ruby_xml_document_validate_schema, 1);
|
1159
|
+
}
|