libxml-ruby 5.0.6 → 6.0.0
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.
- checksums.yaml +4 -4
- data/{HISTORY → CHANGELOG.md} +875 -930
- data/LICENSE +20 -20
- data/README.md +67 -0
- data/Rakefile +13 -34
- data/ext/libxml/extconf.rb +34 -20
- data/ext/libxml/libxml.c +2 -14
- data/ext/libxml/ruby_libxml.h +1 -1
- data/ext/libxml/ruby_xml_attr.c +27 -22
- data/ext/libxml/ruby_xml_attr.h +1 -0
- data/ext/libxml/ruby_xml_attr_decl.c +19 -12
- data/ext/libxml/ruby_xml_attributes.c +18 -9
- data/ext/libxml/ruby_xml_document.c +111 -98
- data/ext/libxml/ruby_xml_document.h +1 -0
- data/ext/libxml/ruby_xml_dtd.c +49 -19
- data/ext/libxml/ruby_xml_dtd.h +1 -0
- data/ext/libxml/ruby_xml_html_parser.c +1 -1
- data/ext/libxml/ruby_xml_html_parser_context.c +19 -6
- data/ext/libxml/ruby_xml_html_parser_context.h +1 -0
- data/ext/libxml/ruby_xml_input_cbg.c +45 -17
- data/ext/libxml/ruby_xml_io.c +3 -1
- data/ext/libxml/ruby_xml_namespace.c +20 -12
- data/ext/libxml/ruby_xml_namespace.h +1 -0
- data/ext/libxml/ruby_xml_namespaces.c +40 -20
- data/ext/libxml/ruby_xml_node.c +71 -32
- data/ext/libxml/ruby_xml_node.h +2 -0
- data/ext/libxml/ruby_xml_parser.c +1 -1
- data/ext/libxml/ruby_xml_parser_context.c +54 -47
- data/ext/libxml/ruby_xml_parser_context.h +1 -0
- data/ext/libxml/ruby_xml_reader.c +25 -15
- data/ext/libxml/ruby_xml_registry.c +31 -0
- data/ext/libxml/ruby_xml_registry.h +22 -0
- data/ext/libxml/ruby_xml_relaxng.c +21 -5
- data/ext/libxml/ruby_xml_relaxng.h +1 -0
- data/ext/libxml/ruby_xml_sax_parser.c +1 -1
- data/ext/libxml/ruby_xml_schema.c +18 -11
- data/ext/libxml/ruby_xml_schema.h +1 -0
- data/ext/libxml/ruby_xml_schema_attribute.c +7 -7
- data/ext/libxml/ruby_xml_schema_element.c +8 -8
- data/ext/libxml/ruby_xml_schema_facet.c +7 -7
- data/ext/libxml/ruby_xml_schema_type.c +12 -19
- data/ext/libxml/ruby_xml_version.h +4 -4
- data/ext/libxml/ruby_xml_writer.c +18 -6
- data/ext/libxml/ruby_xml_xpath.c +2 -2
- data/ext/libxml/ruby_xml_xpath.h +1 -1
- data/ext/libxml/ruby_xml_xpath_context.c +72 -26
- data/ext/libxml/ruby_xml_xpath_expression.c +11 -5
- data/ext/libxml/ruby_xml_xpath_expression.h +1 -0
- data/ext/libxml/ruby_xml_xpath_object.c +69 -54
- data/ext/libxml/ruby_xml_xpath_object.h +3 -1
- data/ext/vc/libxml_ruby/libxml_ruby.vcxproj +271 -0
- data/ext/xcode/libxml-ruby.xcodeproj/project.pbxproj +633 -0
- data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- data/ext/xcode/libxml-ruby.xcodeproj/xcshareddata/xcschemes/libxml-ruby.xcscheme +80 -0
- data/lib/libxml/document.rb +0 -29
- data/lib/libxml/error.rb +30 -3
- data/lib/libxml/html_parser.rb +0 -16
- data/lib/libxml/node.rb +1 -3
- data/lib/libxml/parser.rb +0 -8
- data/lib/libxml/schema/attribute.rb +27 -19
- data/lib/libxml/schema/element.rb +20 -0
- data/lib/libxml/schema/type.rb +44 -21
- data/lib/libxml/schema.rb +47 -47
- data/lib/libxml-ruby.rb +30 -30
- data/libxml-ruby.gemspec +12 -16
- data/test/c14n/result/1-1-without-comments/example-1 +3 -3
- data/test/c14n/result/1-1-without-comments/example-2 +10 -10
- data/test/c14n/result/1-1-without-comments/example-3 +13 -13
- data/test/c14n/result/1-1-without-comments/example-4 +8 -8
- data/test/c14n/result/1-1-without-comments/example-5 +2 -2
- data/test/c14n/result/with-comments/example-1 +5 -5
- data/test/c14n/result/with-comments/example-2 +10 -10
- data/test/c14n/result/with-comments/example-3 +13 -13
- data/test/c14n/result/with-comments/example-4 +8 -8
- data/test/c14n/result/with-comments/example-5 +3 -3
- data/test/c14n/result/without-comments/example-1 +3 -3
- data/test/c14n/result/without-comments/example-2 +10 -10
- data/test/c14n/result/without-comments/example-3 +13 -13
- data/test/c14n/result/without-comments/example-4 +8 -8
- data/test/c14n/result/without-comments/example-5 +2 -2
- data/test/test_attr.rb +179 -180
- data/test/test_attr_decl.rb +131 -131
- data/test/test_attributes.rb +135 -135
- data/test/test_canonicalize.rb +122 -120
- data/test/test_document.rb +2 -4
- data/test/test_dtd.rb +12 -4
- data/test/test_encoding_sax.rb +114 -114
- data/test/test_error.rb +1 -1
- data/test/test_html_parser.rb +6 -2
- data/test/test_html_parser_context.rb +22 -22
- data/test/test_input_callbacks.rb +36 -0
- data/test/test_namespace.rb +1 -1
- data/test/test_namespaces.rb +200 -200
- data/test/test_node.rb +16 -0
- data/test/test_node_cdata.rb +50 -50
- data/test/test_node_comment.rb +32 -32
- data/test/test_node_copy.rb +40 -40
- data/test/test_node_edit.rb +176 -158
- data/test/test_node_pi.rb +37 -37
- data/test/test_node_text.rb +69 -69
- data/test/test_node_xlink.rb +28 -28
- data/test/test_parser.rb +5 -41
- data/test/test_parser_context.rb +198 -198
- data/test/test_properties.rb +38 -38
- data/test/test_reader.rb +55 -6
- data/test/test_relaxng.rb +59 -53
- data/test/test_sax_parser.rb +345 -345
- data/test/test_schema.rb +28 -0
- data/test/test_traversal.rb +152 -152
- data/test/test_writer.rb +0 -31
- data/test/test_xinclude.rb +20 -20
- data/test/test_xml.rb +3 -7
- data/test/test_xpath.rb +244 -244
- data/test/test_xpath_context.rb +87 -87
- data/test/test_xpath_expression.rb +37 -37
- metadata +32 -25
- data/README.rdoc +0 -208
- data/ext/libxml/extconf.h +0 -4
- data/ext/libxml/ruby_xml_cbg.c +0 -85
- data/lib/libxml/hpricot.rb +0 -78
- data/lib/libxml.rb +0 -5
- data/lib/xml/libxml.rb +0 -10
- data/lib/xml.rb +0 -14
- data/script/benchmark/depixelate +0 -634
- data/script/benchmark/hamlet.xml +0 -9055
- data/script/benchmark/parsecount +0 -170
- data/script/benchmark/sock_entries.xml +0 -507
- data/script/benchmark/throughput +0 -41
- data/script/test +0 -6
- data/test/test_deprecated_require.rb +0 -12
|
@@ -129,14 +129,21 @@ static htmlParserCtxtPtr htmlNewParserCtxt(void)
|
|
|
129
129
|
}
|
|
130
130
|
#endif
|
|
131
131
|
|
|
132
|
-
static void rxml_html_parser_context_free(
|
|
132
|
+
static void rxml_html_parser_context_free(void* data)
|
|
133
133
|
{
|
|
134
|
+
htmlParserCtxtPtr ctxt = (htmlParserCtxtPtr)data;
|
|
134
135
|
htmlFreeParserCtxt(ctxt);
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
const rb_data_type_t rxml_html_parser_context_type = {
|
|
139
|
+
"LibXML::XML::HTMLParser::Context",
|
|
140
|
+
{NULL, rxml_html_parser_context_free, NULL},
|
|
141
|
+
&rxml_parser_context_type, NULL, 0
|
|
142
|
+
};
|
|
143
|
+
|
|
137
144
|
static VALUE rxml_html_parser_context_wrap(htmlParserCtxtPtr ctxt)
|
|
138
145
|
{
|
|
139
|
-
return
|
|
146
|
+
return TypedData_Wrap_Struct(cXMLHtmlParserContext, &rxml_html_parser_context_type, ctxt);
|
|
140
147
|
}
|
|
141
148
|
|
|
142
149
|
/* call-seq:
|
|
@@ -275,7 +282,7 @@ static VALUE rxml_html_parser_context_close(VALUE self)
|
|
|
275
282
|
{
|
|
276
283
|
htmlParserCtxtPtr ctxt;
|
|
277
284
|
xmlParserInputPtr xinput;
|
|
278
|
-
|
|
285
|
+
TypedData_Get_Struct(self, htmlParserCtxt, &rxml_html_parser_context_type, ctxt);
|
|
279
286
|
|
|
280
287
|
while ((xinput = inputPop(ctxt)) != NULL)
|
|
281
288
|
{
|
|
@@ -293,7 +300,7 @@ static VALUE rxml_html_parser_context_close(VALUE self)
|
|
|
293
300
|
static VALUE rxml_html_parser_context_disable_cdata_set(VALUE self, VALUE value)
|
|
294
301
|
{
|
|
295
302
|
htmlParserCtxtPtr ctxt;
|
|
296
|
-
|
|
303
|
+
TypedData_Get_Struct(self, htmlParserCtxt, &rxml_html_parser_context_type, ctxt);
|
|
297
304
|
|
|
298
305
|
if (ctxt->sax == NULL)
|
|
299
306
|
rb_raise(rb_eRuntimeError, "Sax handler is not yet set");
|
|
@@ -320,9 +327,8 @@ static VALUE rxml_html_parser_context_options_set(VALUE self, VALUE options)
|
|
|
320
327
|
{
|
|
321
328
|
int xml_options = NUM2INT(options);
|
|
322
329
|
htmlParserCtxtPtr ctxt;
|
|
323
|
-
Check_Type(options, T_FIXNUM);
|
|
324
330
|
|
|
325
|
-
|
|
331
|
+
TypedData_Get_Struct(self, htmlParserCtxt, &rxml_html_parser_context_type, ctxt);
|
|
326
332
|
htmlCtxtUseOptions(ctxt, xml_options);
|
|
327
333
|
|
|
328
334
|
#if LIBXML_VERSION >= 20707
|
|
@@ -337,10 +343,17 @@ static VALUE rxml_html_parser_context_options_set(VALUE self, VALUE options)
|
|
|
337
343
|
return self;
|
|
338
344
|
}
|
|
339
345
|
|
|
346
|
+
static VALUE rxml_html_parser_context_alloc(VALUE klass)
|
|
347
|
+
{
|
|
348
|
+
xmlParserCtxtPtr ctxt = htmlNewParserCtxt();
|
|
349
|
+
return TypedData_Wrap_Struct(klass, &rxml_html_parser_context_type, ctxt);
|
|
350
|
+
}
|
|
351
|
+
|
|
340
352
|
void rxml_init_html_parser_context(void)
|
|
341
353
|
{
|
|
342
354
|
IO_ATTR = ID2SYM(rb_intern("@io"));
|
|
343
355
|
cXMLHtmlParserContext = rb_define_class_under(cXMLHtmlParser, "Context", cXMLParserContext);
|
|
356
|
+
rb_define_alloc_func(cXMLHtmlParserContext, rxml_html_parser_context_alloc);
|
|
344
357
|
|
|
345
358
|
rb_define_singleton_method(cXMLHtmlParserContext, "file", rxml_html_parser_context_file, -1);
|
|
346
359
|
rb_define_singleton_method(cXMLHtmlParserContext, "io", rxml_html_parser_context_io, -1);
|
|
@@ -8,8 +8,38 @@
|
|
|
8
8
|
* Support for adding custom scheme handlers. */
|
|
9
9
|
|
|
10
10
|
static ic_scheme *first_scheme = 0;
|
|
11
|
+
static int input_callbacks_registered = 0;
|
|
11
12
|
|
|
12
|
-
int ic_match(char const *filename)
|
|
13
|
+
static int ic_match(char const *filename);
|
|
14
|
+
static void* ic_open(char const *filename);
|
|
15
|
+
static int ic_read(void *context, char *buffer, int len);
|
|
16
|
+
static int ic_close(void *context);
|
|
17
|
+
|
|
18
|
+
static void input_callbacks_register_once(void)
|
|
19
|
+
{
|
|
20
|
+
if (input_callbacks_registered)
|
|
21
|
+
return;
|
|
22
|
+
|
|
23
|
+
xmlRegisterInputCallbacks(ic_match, ic_open, ic_read, ic_close);
|
|
24
|
+
input_callbacks_registered = 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static char *ic_strdup(const char *string)
|
|
28
|
+
{
|
|
29
|
+
size_t length = strlen(string) + 1;
|
|
30
|
+
char *copy = ruby_xmalloc(length);
|
|
31
|
+
memcpy(copy, string, length);
|
|
32
|
+
return copy;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static void ic_scheme_free(ic_scheme *scheme)
|
|
36
|
+
{
|
|
37
|
+
rb_gc_unregister_address(&scheme->class);
|
|
38
|
+
ruby_xfree(scheme->scheme_name);
|
|
39
|
+
ruby_xfree(scheme);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static int ic_match(char const *filename)
|
|
13
43
|
{
|
|
14
44
|
ic_scheme *scheme;
|
|
15
45
|
|
|
@@ -27,7 +57,7 @@ int ic_match(char const *filename)
|
|
|
27
57
|
return 0;
|
|
28
58
|
}
|
|
29
59
|
|
|
30
|
-
void* ic_open(char const *filename)
|
|
60
|
+
static void* ic_open(char const *filename)
|
|
31
61
|
{
|
|
32
62
|
ic_doc_context *ic_doc;
|
|
33
63
|
ic_scheme *scheme;
|
|
@@ -38,12 +68,11 @@ void* ic_open(char const *filename)
|
|
|
38
68
|
{
|
|
39
69
|
if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len))
|
|
40
70
|
{
|
|
41
|
-
ic_doc = (ic_doc_context*) malloc(sizeof(ic_doc_context));
|
|
42
|
-
|
|
43
71
|
res = rb_funcall(scheme->class, rb_intern("document_query"), 1,
|
|
44
72
|
rb_str_new2(filename));
|
|
45
73
|
|
|
46
|
-
ic_doc
|
|
74
|
+
ic_doc = ALLOC(ic_doc_context);
|
|
75
|
+
ic_doc->buffer = ic_strdup(StringValueCStr(res));
|
|
47
76
|
|
|
48
77
|
ic_doc->bpos = ic_doc->buffer;
|
|
49
78
|
ic_doc->remaining = (int)strlen(ic_doc->buffer);
|
|
@@ -54,7 +83,7 @@ void* ic_open(char const *filename)
|
|
|
54
83
|
return 0;
|
|
55
84
|
}
|
|
56
85
|
|
|
57
|
-
int ic_read(void *context, char *buffer, int len)
|
|
86
|
+
static int ic_read(void *context, char *buffer, int len)
|
|
58
87
|
{
|
|
59
88
|
ic_doc_context *ic_doc;
|
|
60
89
|
int ret_len;
|
|
@@ -75,7 +104,7 @@ int ic_read(void *context, char *buffer, int len)
|
|
|
75
104
|
return ret_len;
|
|
76
105
|
}
|
|
77
106
|
|
|
78
|
-
int ic_close(void *context)
|
|
107
|
+
static int ic_close(void *context)
|
|
79
108
|
{
|
|
80
109
|
ruby_xfree(((ic_doc_context*) context)->buffer);
|
|
81
110
|
ruby_xfree(context);
|
|
@@ -90,7 +119,7 @@ int ic_close(void *context)
|
|
|
90
119
|
*/
|
|
91
120
|
static VALUE input_callbacks_register_input_callbacks(VALUE self)
|
|
92
121
|
{
|
|
93
|
-
|
|
122
|
+
input_callbacks_register_once();
|
|
94
123
|
return (Qtrue);
|
|
95
124
|
}
|
|
96
125
|
|
|
@@ -107,11 +136,14 @@ static VALUE input_callbacks_add_scheme(VALUE self, VALUE scheme_name,
|
|
|
107
136
|
|
|
108
137
|
Check_Type(scheme_name, T_STRING);
|
|
109
138
|
|
|
110
|
-
|
|
139
|
+
input_callbacks_register_once();
|
|
140
|
+
|
|
141
|
+
scheme = ALLOC(ic_scheme);
|
|
111
142
|
scheme->next_scheme = 0;
|
|
112
|
-
scheme->scheme_name =
|
|
143
|
+
scheme->scheme_name = ic_strdup(StringValueCStr(scheme_name));
|
|
113
144
|
scheme->name_len = (int)strlen(scheme->scheme_name);
|
|
114
|
-
scheme->class = class;
|
|
145
|
+
scheme->class = class;
|
|
146
|
+
rb_gc_register_address(&scheme->class);
|
|
115
147
|
|
|
116
148
|
//fprintf( stderr, "registered: %s, %d, %s\n", scheme->scheme_name, scheme->name_len, scheme->class );
|
|
117
149
|
|
|
@@ -150,9 +182,7 @@ static VALUE input_callbacks_remove_scheme(VALUE self, VALUE scheme_name)
|
|
|
150
182
|
{
|
|
151
183
|
save_scheme = first_scheme->next_scheme;
|
|
152
184
|
|
|
153
|
-
|
|
154
|
-
ruby_xfree(first_scheme);
|
|
155
|
-
|
|
185
|
+
ic_scheme_free(first_scheme);
|
|
156
186
|
first_scheme = save_scheme;
|
|
157
187
|
return Qtrue;
|
|
158
188
|
}
|
|
@@ -165,9 +195,7 @@ static VALUE input_callbacks_remove_scheme(VALUE self, VALUE scheme_name)
|
|
|
165
195
|
{
|
|
166
196
|
save_scheme = scheme->next_scheme->next_scheme;
|
|
167
197
|
|
|
168
|
-
|
|
169
|
-
ruby_xfree(scheme->next_scheme);
|
|
170
|
-
|
|
198
|
+
ic_scheme_free(scheme->next_scheme);
|
|
171
199
|
scheme->next_scheme = save_scheme;
|
|
172
200
|
return Qtrue;
|
|
173
201
|
}
|
data/ext/libxml/ruby_xml_io.c
CHANGED
|
@@ -19,6 +19,8 @@ int rxml_read_callback(void *context, char *buffer, int len)
|
|
|
19
19
|
return 0;
|
|
20
20
|
|
|
21
21
|
size = RSTRING_LEN(string);
|
|
22
|
+
if (size > (size_t)len)
|
|
23
|
+
size = (size_t)len;
|
|
22
24
|
memcpy(buffer, StringValuePtr(string), size);
|
|
23
25
|
|
|
24
26
|
return (int)size;
|
|
@@ -30,7 +32,7 @@ int rxml_write_callback(VALUE io, const char *buffer, int len)
|
|
|
30
32
|
{
|
|
31
33
|
// Could be StringIO
|
|
32
34
|
VALUE written, string;
|
|
33
|
-
string = rb_external_str_new_with_enc(buffer, (long)
|
|
35
|
+
string = rb_external_str_new_with_enc(buffer, (long)len, rb_enc_get(io));
|
|
34
36
|
written = rb_funcall(io, WRITE_METHOD, 1, string);
|
|
35
37
|
return NUM2INT(written);
|
|
36
38
|
}
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
VALUE cXMLNamespace;
|
|
7
7
|
|
|
8
|
+
const rb_data_type_t rxml_namespace_type = {
|
|
9
|
+
"libxml/namespace",
|
|
10
|
+
{NULL, NULL, NULL},
|
|
11
|
+
};
|
|
12
|
+
|
|
8
13
|
/* Document-class: LibXML::XML::Namespace
|
|
9
14
|
*
|
|
10
15
|
* The Namespace class represents an XML namespace.
|
|
@@ -26,12 +31,12 @@ VALUE cXMLNamespace;
|
|
|
26
31
|
|
|
27
32
|
static VALUE rxml_namespace_alloc(VALUE klass)
|
|
28
33
|
{
|
|
29
|
-
return
|
|
34
|
+
return TypedData_Wrap_Struct(klass, &rxml_namespace_type, NULL);
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
VALUE rxml_namespace_wrap(xmlNsPtr xns)
|
|
33
38
|
{
|
|
34
|
-
return
|
|
39
|
+
return TypedData_Wrap_Struct(cXMLNamespace, &rxml_namespace_type, xns);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
|
|
@@ -50,15 +55,14 @@ static VALUE rxml_namespace_initialize(VALUE self, VALUE node, VALUE prefix,
|
|
|
50
55
|
xmlChar *xmlPrefix;
|
|
51
56
|
xmlNsPtr xns;
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
Data_Get_Struct(node, xmlNode, xnode);
|
|
58
|
+
TypedData_Get_Struct(node, xmlNode, &rxml_node_data_type, xnode);
|
|
55
59
|
xmlResetLastError();
|
|
56
60
|
|
|
57
61
|
/* Prefix can be null - that means its the default namespace */
|
|
58
62
|
xmlPrefix = NIL_P(prefix) ? NULL : (xmlChar *)StringValuePtr(prefix);
|
|
59
63
|
xns = xmlNewNs(xnode, (xmlChar*) StringValuePtr(href), xmlPrefix);
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
RTYPEDDATA_DATA(self) = xns;
|
|
62
66
|
return self;
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -75,7 +79,7 @@ static VALUE rxml_namespace_initialize(VALUE self, VALUE node, VALUE prefix,
|
|
|
75
79
|
static VALUE rxml_namespace_href_get(VALUE self)
|
|
76
80
|
{
|
|
77
81
|
xmlNsPtr xns;
|
|
78
|
-
|
|
82
|
+
TypedData_Get_Struct(self, xmlNs, &rxml_namespace_type, xns);
|
|
79
83
|
if (xns->href == NULL)
|
|
80
84
|
return Qnil;
|
|
81
85
|
else
|
|
@@ -91,7 +95,7 @@ static VALUE rxml_namespace_href_get(VALUE self)
|
|
|
91
95
|
static VALUE rxml_namespace_node_type(VALUE self)
|
|
92
96
|
{
|
|
93
97
|
xmlNsPtr xns;
|
|
94
|
-
|
|
98
|
+
TypedData_Get_Struct(self, xmlNs, &rxml_namespace_type, xns);
|
|
95
99
|
return INT2NUM(xns->type);
|
|
96
100
|
}
|
|
97
101
|
|
|
@@ -110,7 +114,7 @@ static VALUE rxml_namespace_node_type(VALUE self)
|
|
|
110
114
|
static VALUE rxml_namespace_prefix_get(VALUE self)
|
|
111
115
|
{
|
|
112
116
|
xmlNsPtr xns;
|
|
113
|
-
|
|
117
|
+
TypedData_Get_Struct(self, xmlNs, &rxml_namespace_type, xns);
|
|
114
118
|
if (xns->prefix == NULL)
|
|
115
119
|
return Qnil;
|
|
116
120
|
else
|
|
@@ -132,11 +136,15 @@ static VALUE rxml_namespace_prefix_get(VALUE self)
|
|
|
132
136
|
static VALUE rxml_namespace_next(VALUE self)
|
|
133
137
|
{
|
|
134
138
|
xmlNsPtr xns;
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
TypedData_Get_Struct(self, xmlNs, &rxml_namespace_type, xns);
|
|
140
|
+
/* Guard against libxml2's XPath hack where xns->next stores a parent
|
|
141
|
+
element pointer instead of the next namespace (see xmlXPathNodeSetAddNs
|
|
142
|
+
in xpath.c). xmlNs.type and xmlNode.type share the same struct offset,
|
|
143
|
+
so checking the type is safe even when next points to an xmlNode. */
|
|
144
|
+
if (xns == NULL || xns->next == NULL || xns->next->type != XML_LOCAL_NAMESPACE)
|
|
137
145
|
return (Qnil);
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
|
|
147
|
+
return rxml_namespace_wrap(xns->next);
|
|
140
148
|
}
|
|
141
149
|
|
|
142
150
|
void rxml_init_namespace(void)
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
VALUE cXMLNamespaces;
|
|
7
7
|
|
|
8
|
+
static const rb_data_type_t rxml_namespaces_type = {
|
|
9
|
+
"libxml/namespaces",
|
|
10
|
+
{NULL, NULL, NULL},
|
|
11
|
+
};
|
|
12
|
+
|
|
8
13
|
/* Document-class: LibXML::XML::Namespaces
|
|
9
14
|
*
|
|
10
15
|
* The XML::Namespaces class is used to access information about
|
|
@@ -38,7 +43,7 @@ VALUE cXMLNamespaces;
|
|
|
38
43
|
|
|
39
44
|
static VALUE rxml_namespaces_alloc(VALUE klass)
|
|
40
45
|
{
|
|
41
|
-
return
|
|
46
|
+
return TypedData_Wrap_Struct(klass, &rxml_namespaces_type, NULL);
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
/*
|
|
@@ -58,10 +63,9 @@ static VALUE rxml_namespaces_initialize(VALUE self, VALUE node)
|
|
|
58
63
|
{
|
|
59
64
|
xmlNodePtr xnode;
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
Data_Get_Struct(node, xmlNode, xnode);
|
|
66
|
+
TypedData_Get_Struct(node, xmlNode, &rxml_node_data_type, xnode);
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
RTYPEDDATA_DATA(self) = xnode;
|
|
65
69
|
return self;
|
|
66
70
|
}
|
|
67
71
|
|
|
@@ -83,7 +87,7 @@ static VALUE rxml_namespaces_definitions(VALUE self)
|
|
|
83
87
|
xmlNsPtr xns;
|
|
84
88
|
VALUE arr;
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
87
91
|
|
|
88
92
|
arr = rb_ary_new();
|
|
89
93
|
xns = xnode->nsDef;
|
|
@@ -112,24 +116,41 @@ static VALUE rxml_namespaces_definitions(VALUE self)
|
|
|
112
116
|
* ..
|
|
113
117
|
* end
|
|
114
118
|
*/
|
|
119
|
+
static VALUE rxml_namespaces_each_yield(VALUE data)
|
|
120
|
+
{
|
|
121
|
+
xmlNsPtr*nsList = (xmlNsPtr*)data;
|
|
122
|
+
xmlNsPtr*xns;
|
|
123
|
+
|
|
124
|
+
for (xns = nsList; *xns != NULL; xns++)
|
|
125
|
+
{
|
|
126
|
+
VALUE ns = rxml_namespace_wrap(*xns);
|
|
127
|
+
rb_yield(ns);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return Qnil;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static VALUE rxml_namespaces_free_list(VALUE data)
|
|
134
|
+
{
|
|
135
|
+
xmlNsPtr*nsList = (xmlNsPtr*)data;
|
|
136
|
+
xmlFree(nsList);
|
|
137
|
+
return Qnil;
|
|
138
|
+
}
|
|
139
|
+
|
|
115
140
|
static VALUE rxml_namespaces_each(VALUE self)
|
|
116
141
|
{
|
|
117
142
|
xmlNodePtr xnode;
|
|
118
|
-
xmlNsPtr
|
|
143
|
+
xmlNsPtr*nsList;
|
|
119
144
|
|
|
120
|
-
|
|
145
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
121
146
|
|
|
122
147
|
nsList = xmlGetNsList(xnode->doc, xnode);
|
|
123
148
|
|
|
124
149
|
if (nsList == NULL)
|
|
125
150
|
return (Qnil);
|
|
126
151
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
VALUE ns = rxml_namespace_wrap(*xns);
|
|
130
|
-
rb_yield(ns);
|
|
131
|
-
}
|
|
132
|
-
xmlFree(nsList);
|
|
152
|
+
rb_ensure(rxml_namespaces_each_yield, (VALUE)nsList,
|
|
153
|
+
rxml_namespaces_free_list, (VALUE)nsList);
|
|
133
154
|
|
|
134
155
|
return Qnil;
|
|
135
156
|
}
|
|
@@ -157,7 +178,7 @@ static VALUE rxml_namespaces_find_by_href(VALUE self, VALUE href)
|
|
|
157
178
|
xmlNsPtr xns;
|
|
158
179
|
|
|
159
180
|
Check_Type(href, T_STRING);
|
|
160
|
-
|
|
181
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
161
182
|
|
|
162
183
|
xns = xmlSearchNsByHref(xnode->doc, xnode, (xmlChar*) StringValuePtr(href));
|
|
163
184
|
if (xns)
|
|
@@ -196,7 +217,7 @@ static VALUE rxml_namespaces_find_by_prefix(VALUE self, VALUE prefix)
|
|
|
196
217
|
xprefix = (xmlChar*) StringValuePtr(prefix);
|
|
197
218
|
}
|
|
198
219
|
|
|
199
|
-
|
|
220
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
200
221
|
|
|
201
222
|
xns = xmlSearchNs(xnode->doc, xnode, xprefix);
|
|
202
223
|
if (xns)
|
|
@@ -221,7 +242,7 @@ static VALUE rxml_namespaces_find_by_prefix(VALUE self, VALUE prefix)
|
|
|
221
242
|
static VALUE rxml_namespaces_namespace_get(VALUE self)
|
|
222
243
|
{
|
|
223
244
|
xmlNodePtr xnode;
|
|
224
|
-
|
|
245
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
225
246
|
|
|
226
247
|
if (xnode->ns)
|
|
227
248
|
return rxml_namespace_wrap(xnode->ns);
|
|
@@ -253,10 +274,9 @@ static VALUE rxml_namespaces_namespace_set(VALUE self, VALUE ns)
|
|
|
253
274
|
xmlNodePtr xnode;
|
|
254
275
|
xmlNsPtr xns;
|
|
255
276
|
|
|
256
|
-
|
|
277
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
257
278
|
|
|
258
|
-
|
|
259
|
-
Data_Get_Struct(ns, xmlNs, xns);
|
|
279
|
+
TypedData_Get_Struct(ns, xmlNs, &rxml_namespace_type, xns);
|
|
260
280
|
|
|
261
281
|
xmlSetNs(xnode, xns);
|
|
262
282
|
return self;
|
|
@@ -271,7 +291,7 @@ static VALUE rxml_namespaces_namespace_set(VALUE self, VALUE ns)
|
|
|
271
291
|
static VALUE rxml_namespaces_node_get(VALUE self)
|
|
272
292
|
{
|
|
273
293
|
xmlNodePtr xnode;
|
|
274
|
-
|
|
294
|
+
TypedData_Get_Struct(self, xmlNode, &rxml_namespaces_type, xnode);
|
|
275
295
|
return rxml_node_wrap(xnode);
|
|
276
296
|
}
|
|
277
297
|
|
data/ext/libxml/ruby_xml_node.c
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
VALUE cXMLNode;
|
|
10
10
|
|
|
11
|
+
#ifndef TYPED_DATA_EMBEDDED
|
|
12
|
+
#define TYPED_DATA_EMBEDDED ((VALUE)1)
|
|
13
|
+
#endif
|
|
14
|
+
|
|
11
15
|
/* Document-class: LibXML::XML::Node
|
|
12
16
|
*
|
|
13
17
|
* Nodes are the primary objects that make up an XML document.
|
|
@@ -26,9 +30,9 @@ VALUE cXMLNode;
|
|
|
26
30
|
* have a parent and do not belong to a document). In these cases,
|
|
27
31
|
* the bindings manage the memory. They do this by installing a free
|
|
28
32
|
* function and storing a back pointer to the Ruby object from the xmlnode
|
|
29
|
-
* using
|
|
30
|
-
* goes out of scope, the underlying libxml structure is freed.
|
|
31
|
-
* itself then frees all child node (recursively).
|
|
33
|
+
* using a pointer-keyed registry (see ruby_xml_registry.c). When the
|
|
34
|
+
* Ruby object goes out of scope, the underlying libxml structure is freed.
|
|
35
|
+
* Libxml itself then frees all child node (recursively).
|
|
32
36
|
*
|
|
33
37
|
* For all other nodes (the vast majority), the bindings create temporary
|
|
34
38
|
* Ruby objects that get freed once they go out of scope. Thus there can be
|
|
@@ -46,29 +50,71 @@ VALUE cXMLNode;
|
|
|
46
50
|
* and are no longer in scope (since if they were the document would not be freed).
|
|
47
51
|
*/
|
|
48
52
|
|
|
49
|
-
static void rxml_node_free(
|
|
53
|
+
static void rxml_node_free(void *data)
|
|
50
54
|
{
|
|
55
|
+
xmlNodePtr xnode = (xmlNodePtr)data;
|
|
56
|
+
if (!xnode) return;
|
|
57
|
+
|
|
51
58
|
/* The ruby object wrapping the xml object no longer exists and this
|
|
52
|
-
is a standalone node without a document or parent so ruby is
|
|
59
|
+
is a standalone node without a document or parent so ruby is
|
|
53
60
|
responsible for freeing the underlying node.*/
|
|
54
61
|
if (xnode->doc == NULL && xnode->parent == NULL)
|
|
55
62
|
{
|
|
56
|
-
|
|
57
|
-
xnode->_private = NULL;
|
|
63
|
+
rxml_registry_unregister(xnode);
|
|
58
64
|
xmlFreeNode(xnode);
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
67
|
|
|
68
|
+
/* Three TypedData types are used for nodes, all sharing rxml_node_data_type
|
|
69
|
+
* as the parent type so that TypedData_Get_Struct type checks pass for any
|
|
70
|
+
* variant:
|
|
71
|
+
*
|
|
72
|
+
* rxml_node_data_type - Default. Marks the owning document to prevent
|
|
73
|
+
* GC from collecting it. No free function since
|
|
74
|
+
* libxml owns the node memory.
|
|
75
|
+
*
|
|
76
|
+
* rxml_node_unmanaged_data_type - No mark, no free. Used for transient nodes
|
|
77
|
+
* whose lifetime is not controlled by Ruby (e.g.
|
|
78
|
+
* nodes returned by xmlTextReaderExpand that are
|
|
79
|
+
* freed on the next reader read call).
|
|
80
|
+
*
|
|
81
|
+
* rxml_node_managed_data_type - Marks the document and frees standalone nodes
|
|
82
|
+
* (no doc, no parent) when the Ruby wrapper is
|
|
83
|
+
* collected. Used for nodes created from Ruby
|
|
84
|
+
* that have not yet been inserted into a document.
|
|
85
|
+
*/
|
|
86
|
+
const rb_data_type_t rxml_node_data_type = {
|
|
87
|
+
.wrap_struct_name = "LibXML::XML::Node",
|
|
88
|
+
.function = { .dmark = (RUBY_DATA_FUNC)rxml_node_mark, .dfree = NULL },
|
|
89
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const rb_data_type_t rxml_node_unmanaged_data_type = {
|
|
93
|
+
.wrap_struct_name = "LibXML::XML::Node (unmanaged)",
|
|
94
|
+
.function = { .dmark = NULL, .dfree = NULL },
|
|
95
|
+
.parent = &rxml_node_data_type,
|
|
96
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
static const rb_data_type_t rxml_node_managed_data_type = {
|
|
100
|
+
.wrap_struct_name = "LibXML::XML::Node (managed)",
|
|
101
|
+
.function = { .dmark = (RUBY_DATA_FUNC)rxml_node_mark, .dfree = rxml_node_free },
|
|
102
|
+
.parent = &rxml_node_data_type,
|
|
103
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
104
|
+
};
|
|
105
|
+
|
|
62
106
|
void rxml_node_manage(xmlNodePtr xnode, VALUE node)
|
|
63
107
|
{
|
|
64
|
-
|
|
65
|
-
|
|
108
|
+
VALUE *type_ptr = (VALUE *)&RTYPEDDATA(node)->type;
|
|
109
|
+
*type_ptr = (*type_ptr & TYPED_DATA_EMBEDDED) | (VALUE)&rxml_node_managed_data_type;
|
|
110
|
+
rxml_registry_register(xnode, node);
|
|
66
111
|
}
|
|
67
112
|
|
|
68
113
|
void rxml_node_unmanage(xmlNodePtr xnode, VALUE node)
|
|
69
114
|
{
|
|
70
|
-
|
|
71
|
-
|
|
115
|
+
VALUE *type_ptr = (VALUE *)&RTYPEDDATA(node)->type;
|
|
116
|
+
*type_ptr = (*type_ptr & TYPED_DATA_EMBEDDED) | (VALUE)&rxml_node_data_type;
|
|
117
|
+
rxml_registry_unregister(xnode);
|
|
72
118
|
}
|
|
73
119
|
|
|
74
120
|
xmlNodePtr rxml_node_root(xmlNodePtr xnode)
|
|
@@ -87,20 +133,16 @@ void rxml_node_mark(xmlNodePtr xnode)
|
|
|
87
133
|
{
|
|
88
134
|
if (xnode->doc)
|
|
89
135
|
{
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
rb_gc_mark(doc);
|
|
94
|
-
}
|
|
136
|
+
VALUE doc = rxml_registry_lookup(xnode->doc);
|
|
137
|
+
if (!NIL_P(doc))
|
|
138
|
+
rb_gc_mark(doc);
|
|
95
139
|
}
|
|
96
140
|
else if (xnode->parent)
|
|
97
141
|
{
|
|
98
142
|
xmlNodePtr root = rxml_node_root(xnode);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
VALUE node = (VALUE)root->_private;
|
|
143
|
+
VALUE node = rxml_registry_lookup(root);
|
|
144
|
+
if (!NIL_P(node))
|
|
102
145
|
rb_gc_mark(node);
|
|
103
|
-
}
|
|
104
146
|
}
|
|
105
147
|
}
|
|
106
148
|
|
|
@@ -109,13 +151,10 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
|
|
|
109
151
|
VALUE result = Qnil;
|
|
110
152
|
|
|
111
153
|
// Is this node already wrapped?
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
result = (VALUE)xnode->_private;
|
|
115
|
-
}
|
|
116
|
-
else
|
|
154
|
+
result = rxml_registry_lookup(xnode);
|
|
155
|
+
if (NIL_P(result))
|
|
117
156
|
{
|
|
118
|
-
result =
|
|
157
|
+
result = TypedData_Wrap_Struct(cXMLNode, &rxml_node_data_type, xnode);
|
|
119
158
|
}
|
|
120
159
|
|
|
121
160
|
if (!xnode->doc && !xnode->parent)
|
|
@@ -128,13 +167,13 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
|
|
|
128
167
|
static VALUE rxml_node_alloc(VALUE klass)
|
|
129
168
|
{
|
|
130
169
|
// This node was created from Ruby so we are responsible for freeing it not libxml
|
|
131
|
-
return
|
|
170
|
+
return TypedData_Wrap_Struct(klass, &rxml_node_data_type, NULL);
|
|
132
171
|
}
|
|
133
172
|
|
|
134
173
|
static xmlNodePtr rxml_get_xnode(VALUE node)
|
|
135
174
|
{
|
|
136
175
|
xmlNodePtr result;
|
|
137
|
-
|
|
176
|
+
TypedData_Get_Struct(node, xmlNode, &rxml_node_data_type, result);
|
|
138
177
|
|
|
139
178
|
if (!result)
|
|
140
179
|
rb_raise(rb_eRuntimeError, "This node has already been freed.");
|
|
@@ -283,7 +322,7 @@ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
283
322
|
name = rb_obj_as_string(name);
|
|
284
323
|
|
|
285
324
|
if (!NIL_P(ns))
|
|
286
|
-
|
|
325
|
+
TypedData_Get_Struct(ns, xmlNs, &rxml_namespace_type, xns);
|
|
287
326
|
|
|
288
327
|
xnode = xmlNewNode(xns, (xmlChar*) StringValuePtr(name));
|
|
289
328
|
|
|
@@ -291,7 +330,7 @@ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
291
330
|
rxml_raise(xmlGetLastError());
|
|
292
331
|
|
|
293
332
|
// Link the ruby wrapper to the underlying libxml node
|
|
294
|
-
|
|
333
|
+
RTYPEDDATA_DATA(self) = xnode;
|
|
295
334
|
|
|
296
335
|
// Ruby is in charge of managing this node's memory
|
|
297
336
|
rxml_node_manage(xnode, self);
|
|
@@ -329,7 +368,7 @@ static VALUE rxml_node_modify_dom(VALUE self, VALUE target,
|
|
|
329
368
|
|
|
330
369
|
/* Assume the target was freed, we need to fix up the ruby object to point to the
|
|
331
370
|
newly returned node. */
|
|
332
|
-
|
|
371
|
+
RTYPEDDATA_DATA(target) = xresult;
|
|
333
372
|
|
|
334
373
|
return target;
|
|
335
374
|
}
|
|
@@ -533,7 +572,7 @@ static VALUE rxml_node_doc(VALUE self)
|
|
|
533
572
|
if (xdoc == NULL)
|
|
534
573
|
return (Qnil);
|
|
535
574
|
|
|
536
|
-
return (
|
|
575
|
+
return rxml_registry_lookup(xdoc);
|
|
537
576
|
}
|
|
538
577
|
|
|
539
578
|
/*
|
data/ext/libxml/ruby_xml_node.h
CHANGED
|
@@ -64,7 +64,7 @@ static VALUE rxml_parser_parse(VALUE self)
|
|
|
64
64
|
xmlParserCtxtPtr ctxt;
|
|
65
65
|
VALUE context = rb_ivar_get(self, CONTEXT_ATTR);
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
TypedData_Get_Struct(context, xmlParserCtxt, &rxml_parser_context_type, ctxt);
|
|
68
68
|
|
|
69
69
|
if ((xmlParseDocument(ctxt) == -1 || !ctxt->wellFormed) && ! ctxt->recovery)
|
|
70
70
|
{
|