nokogiri 1.10.3 → 1.13.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of nokogiri might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/LICENSE-DEPENDENCIES.md +1173 -884
- data/LICENSE.md +1 -1
- data/README.md +178 -96
- data/bin/nokogiri +63 -50
- data/dependencies.yml +13 -62
- data/ext/nokogiri/depend +38 -358
- data/ext/nokogiri/extconf.rb +761 -424
- data/ext/nokogiri/gumbo.c +584 -0
- data/ext/nokogiri/html4_document.c +166 -0
- data/ext/nokogiri/html4_element_description.c +294 -0
- data/ext/nokogiri/html4_entity_lookup.c +37 -0
- data/ext/nokogiri/html4_sax_parser_context.c +119 -0
- data/ext/nokogiri/html4_sax_push_parser.c +95 -0
- data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
- data/ext/nokogiri/nokogiri.c +228 -91
- data/ext/nokogiri/nokogiri.h +199 -88
- data/ext/nokogiri/test_global_handlers.c +40 -0
- data/ext/nokogiri/xml_attr.c +17 -17
- data/ext/nokogiri/xml_attribute_decl.c +21 -21
- data/ext/nokogiri/xml_cdata.c +14 -19
- data/ext/nokogiri/xml_comment.c +19 -26
- data/ext/nokogiri/xml_document.c +296 -220
- data/ext/nokogiri/xml_document_fragment.c +12 -16
- data/ext/nokogiri/xml_dtd.c +64 -58
- data/ext/nokogiri/xml_element_content.c +31 -26
- data/ext/nokogiri/xml_element_decl.c +25 -25
- data/ext/nokogiri/xml_encoding_handler.c +43 -18
- data/ext/nokogiri/xml_entity_decl.c +37 -35
- data/ext/nokogiri/xml_entity_reference.c +16 -18
- data/ext/nokogiri/xml_namespace.c +98 -53
- data/ext/nokogiri/xml_node.c +1065 -653
- data/ext/nokogiri/xml_node_set.c +178 -166
- data/ext/nokogiri/xml_processing_instruction.c +17 -19
- data/ext/nokogiri/xml_reader.c +277 -175
- data/ext/nokogiri/xml_relax_ng.c +52 -28
- data/ext/nokogiri/xml_sax_parser.c +112 -112
- data/ext/nokogiri/xml_sax_parser_context.c +112 -86
- data/ext/nokogiri/xml_sax_push_parser.c +36 -27
- data/ext/nokogiri/xml_schema.c +114 -35
- data/ext/nokogiri/xml_syntax_error.c +42 -21
- data/ext/nokogiri/xml_text.c +14 -18
- data/ext/nokogiri/xml_xpath_context.c +226 -115
- data/ext/nokogiri/xslt_stylesheet.c +265 -173
- data/gumbo-parser/CHANGES.md +63 -0
- data/gumbo-parser/Makefile +101 -0
- data/gumbo-parser/THANKS +27 -0
- data/gumbo-parser/src/Makefile +34 -0
- data/gumbo-parser/src/README.md +41 -0
- data/gumbo-parser/src/ascii.c +75 -0
- data/gumbo-parser/src/ascii.h +115 -0
- data/gumbo-parser/src/attribute.c +42 -0
- data/gumbo-parser/src/attribute.h +17 -0
- data/gumbo-parser/src/char_ref.c +22225 -0
- data/gumbo-parser/src/char_ref.h +29 -0
- data/gumbo-parser/src/char_ref.rl +2154 -0
- data/gumbo-parser/src/error.c +626 -0
- data/gumbo-parser/src/error.h +148 -0
- data/gumbo-parser/src/foreign_attrs.c +104 -0
- data/gumbo-parser/src/foreign_attrs.gperf +27 -0
- data/gumbo-parser/src/gumbo.h +943 -0
- data/gumbo-parser/src/insertion_mode.h +33 -0
- data/gumbo-parser/src/macros.h +91 -0
- data/gumbo-parser/src/parser.c +4875 -0
- data/gumbo-parser/src/parser.h +41 -0
- data/gumbo-parser/src/replacement.h +33 -0
- data/gumbo-parser/src/string_buffer.c +103 -0
- data/gumbo-parser/src/string_buffer.h +68 -0
- data/gumbo-parser/src/string_piece.c +48 -0
- data/gumbo-parser/src/svg_attrs.c +174 -0
- data/gumbo-parser/src/svg_attrs.gperf +77 -0
- data/gumbo-parser/src/svg_tags.c +137 -0
- data/gumbo-parser/src/svg_tags.gperf +55 -0
- data/gumbo-parser/src/tag.c +222 -0
- data/gumbo-parser/src/tag_lookup.c +382 -0
- data/gumbo-parser/src/tag_lookup.gperf +169 -0
- data/gumbo-parser/src/tag_lookup.h +13 -0
- data/gumbo-parser/src/token_buffer.c +79 -0
- data/gumbo-parser/src/token_buffer.h +71 -0
- data/gumbo-parser/src/token_type.h +17 -0
- data/gumbo-parser/src/tokenizer.c +3463 -0
- data/gumbo-parser/src/tokenizer.h +112 -0
- data/gumbo-parser/src/tokenizer_states.h +339 -0
- data/gumbo-parser/src/utf8.c +245 -0
- data/gumbo-parser/src/utf8.h +164 -0
- data/gumbo-parser/src/util.c +68 -0
- data/gumbo-parser/src/util.h +30 -0
- data/gumbo-parser/src/vector.c +111 -0
- data/gumbo-parser/src/vector.h +45 -0
- data/lib/nokogiri/class_resolver.rb +67 -0
- data/lib/nokogiri/css/node.rb +10 -8
- data/lib/nokogiri/css/parser.rb +397 -377
- data/lib/nokogiri/css/parser.y +250 -245
- data/lib/nokogiri/css/parser_extras.rb +54 -49
- data/lib/nokogiri/css/syntax_error.rb +3 -1
- data/lib/nokogiri/css/tokenizer.rb +107 -104
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +218 -91
- data/lib/nokogiri/css.rb +50 -17
- data/lib/nokogiri/decorators/slop.rb +9 -7
- data/lib/nokogiri/extension.rb +31 -0
- data/lib/nokogiri/gumbo.rb +15 -0
- data/lib/nokogiri/html.rb +38 -27
- data/lib/nokogiri/{html → html4}/builder.rb +4 -2
- data/lib/nokogiri/{html → html4}/document.rb +103 -105
- data/lib/nokogiri/html4/document_fragment.rb +54 -0
- data/lib/nokogiri/{html → html4}/element_description.rb +3 -1
- data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
- data/lib/nokogiri/{html → html4}/entity_lookup.rb +4 -2
- data/lib/nokogiri/{html → html4}/sax/parser.rb +17 -16
- data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
- data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
- data/lib/nokogiri/html4.rb +46 -0
- data/lib/nokogiri/html5/document.rb +91 -0
- data/lib/nokogiri/html5/document_fragment.rb +83 -0
- data/lib/nokogiri/html5/node.rb +100 -0
- data/lib/nokogiri/html5.rb +478 -0
- data/lib/nokogiri/jruby/dependencies.rb +21 -0
- data/lib/nokogiri/syntax_error.rb +2 -0
- data/lib/nokogiri/version/constant.rb +6 -0
- data/lib/nokogiri/version/info.rb +222 -0
- data/lib/nokogiri/version.rb +3 -108
- data/lib/nokogiri/xml/attr.rb +6 -3
- data/lib/nokogiri/xml/attribute_decl.rb +3 -1
- data/lib/nokogiri/xml/builder.rb +97 -53
- data/lib/nokogiri/xml/cdata.rb +3 -1
- data/lib/nokogiri/xml/character_data.rb +2 -0
- data/lib/nokogiri/xml/document.rb +224 -86
- data/lib/nokogiri/xml/document_fragment.rb +46 -44
- data/lib/nokogiri/xml/dtd.rb +4 -2
- data/lib/nokogiri/xml/element_content.rb +2 -0
- data/lib/nokogiri/xml/element_decl.rb +3 -1
- data/lib/nokogiri/xml/entity_decl.rb +4 -2
- data/lib/nokogiri/xml/entity_reference.rb +2 -0
- data/lib/nokogiri/xml/namespace.rb +3 -0
- data/lib/nokogiri/xml/node/save_options.rb +10 -5
- data/lib/nokogiri/xml/node.rb +884 -378
- data/lib/nokogiri/xml/node_set.rb +51 -54
- data/lib/nokogiri/xml/notation.rb +13 -0
- data/lib/nokogiri/xml/parse_options.rb +22 -8
- data/lib/nokogiri/xml/pp/character_data.rb +9 -6
- data/lib/nokogiri/xml/pp/node.rb +25 -26
- data/lib/nokogiri/xml/pp.rb +4 -2
- data/lib/nokogiri/xml/processing_instruction.rb +3 -1
- data/lib/nokogiri/xml/reader.rb +21 -28
- data/lib/nokogiri/xml/relax_ng.rb +8 -2
- data/lib/nokogiri/xml/sax/document.rb +45 -49
- data/lib/nokogiri/xml/sax/parser.rb +38 -34
- data/lib/nokogiri/xml/sax/parser_context.rb +8 -3
- data/lib/nokogiri/xml/sax/push_parser.rb +6 -5
- data/lib/nokogiri/xml/sax.rb +6 -4
- data/lib/nokogiri/xml/schema.rb +19 -9
- data/lib/nokogiri/xml/searchable.rb +112 -72
- data/lib/nokogiri/xml/syntax_error.rb +6 -4
- data/lib/nokogiri/xml/text.rb +2 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
- data/lib/nokogiri/xml/xpath.rb +15 -4
- data/lib/nokogiri/xml/xpath_context.rb +3 -3
- data/lib/nokogiri/xml.rb +38 -37
- data/lib/nokogiri/xslt/stylesheet.rb +3 -1
- data/lib/nokogiri/xslt.rb +29 -20
- data/lib/nokogiri.rb +49 -65
- data/lib/xsd/xmlparser/nokogiri.rb +26 -24
- data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
- data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
- data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +25 -0
- data/patches/libxml2/0005-avoid-isnan-isinf.patch +81 -0
- data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
- data/patches/libxslt/0001-update-automake-files-for-arm64.patch +3037 -0
- data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
- metadata +205 -138
- data/ext/nokogiri/html_document.c +0 -170
- data/ext/nokogiri/html_document.h +0 -10
- data/ext/nokogiri/html_element_description.c +0 -279
- data/ext/nokogiri/html_element_description.h +0 -10
- data/ext/nokogiri/html_entity_lookup.c +0 -32
- data/ext/nokogiri/html_entity_lookup.h +0 -8
- data/ext/nokogiri/html_sax_parser_context.c +0 -116
- data/ext/nokogiri/html_sax_parser_context.h +0 -11
- data/ext/nokogiri/html_sax_push_parser.c +0 -87
- data/ext/nokogiri/html_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_attr.h +0 -9
- data/ext/nokogiri/xml_attribute_decl.h +0 -9
- data/ext/nokogiri/xml_cdata.h +0 -9
- data/ext/nokogiri/xml_comment.h +0 -9
- data/ext/nokogiri/xml_document.h +0 -23
- data/ext/nokogiri/xml_document_fragment.h +0 -10
- data/ext/nokogiri/xml_dtd.h +0 -10
- data/ext/nokogiri/xml_element_content.h +0 -10
- data/ext/nokogiri/xml_element_decl.h +0 -9
- data/ext/nokogiri/xml_encoding_handler.h +0 -8
- data/ext/nokogiri/xml_entity_decl.h +0 -10
- data/ext/nokogiri/xml_entity_reference.h +0 -9
- data/ext/nokogiri/xml_io.c +0 -61
- data/ext/nokogiri/xml_io.h +0 -11
- data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
- data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
- data/ext/nokogiri/xml_namespace.h +0 -14
- data/ext/nokogiri/xml_node.h +0 -13
- data/ext/nokogiri/xml_node_set.h +0 -12
- data/ext/nokogiri/xml_processing_instruction.h +0 -9
- data/ext/nokogiri/xml_reader.h +0 -10
- data/ext/nokogiri/xml_relax_ng.h +0 -9
- data/ext/nokogiri/xml_sax_parser.h +0 -39
- data/ext/nokogiri/xml_sax_parser_context.h +0 -10
- data/ext/nokogiri/xml_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_schema.h +0 -9
- data/ext/nokogiri/xml_syntax_error.h +0 -13
- data/ext/nokogiri/xml_text.h +0 -9
- data/ext/nokogiri/xml_xpath_context.h +0 -10
- data/ext/nokogiri/xslt_stylesheet.h +0 -14
- data/lib/nokogiri/html/document_fragment.rb +0 -49
- data/lib/nokogiri/html/element_description_defaults.rb +0 -671
- data/lib/nokogiri/html/sax/parser_context.rb +0 -16
- data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
- data/patches/libxslt/0001-Fix-security-framework-bypass.patch +0 -120
- data/ports/archives/libxml2-2.9.9.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.33.tar.gz +0 -0
data/ext/nokogiri/xml_node.c
CHANGED
@@ -1,36 +1,71 @@
|
|
1
|
-
#include <
|
1
|
+
#include <nokogiri.h>
|
2
2
|
|
3
|
-
|
3
|
+
// :stopdoc:
|
4
|
+
|
5
|
+
VALUE cNokogiriXmlNode ;
|
6
|
+
static ID id_decorate, id_decorate_bang;
|
7
|
+
|
8
|
+
typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
|
4
9
|
|
5
10
|
#ifdef DEBUG
|
6
|
-
static void
|
11
|
+
static void
|
12
|
+
_xml_node_dealloc(xmlNodePtr x)
|
7
13
|
{
|
8
14
|
NOKOGIRI_DEBUG_START(x)
|
9
15
|
NOKOGIRI_DEBUG_END(x)
|
10
16
|
}
|
11
17
|
#else
|
12
|
-
# define
|
18
|
+
# define _xml_node_dealloc 0
|
13
19
|
#endif
|
14
20
|
|
15
|
-
static void
|
21
|
+
static void
|
22
|
+
_xml_node_mark(xmlNodePtr node)
|
16
23
|
{
|
24
|
+
if (!DOC_RUBY_OBJECT_TEST(node->doc)) {
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
17
28
|
xmlDocPtr doc = node->doc;
|
18
|
-
if(doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
|
19
|
-
if(DOC_RUBY_OBJECT_TEST(doc)) {
|
29
|
+
if (doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
|
30
|
+
if (DOC_RUBY_OBJECT_TEST(doc)) {
|
20
31
|
rb_gc_mark(DOC_RUBY_OBJECT(doc));
|
21
32
|
}
|
22
|
-
} else if(node->doc->_private) {
|
33
|
+
} else if (node->doc->_private) {
|
23
34
|
rb_gc_mark((VALUE)doc->_private);
|
24
35
|
}
|
25
36
|
}
|
26
37
|
|
27
|
-
|
28
|
-
|
38
|
+
#ifdef HAVE_RB_GC_LOCATION
|
39
|
+
static void
|
40
|
+
_xml_node_update_references(xmlNodePtr node)
|
41
|
+
{
|
42
|
+
if (node->_private) {
|
43
|
+
node->_private = (void *)rb_gc_location((VALUE)node->_private);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
#endif
|
29
47
|
|
30
|
-
|
31
|
-
|
48
|
+
typedef void (*gc_callback_t)(void *);
|
49
|
+
|
50
|
+
static const rb_data_type_t nokogiri_node_type = {
|
51
|
+
"Nokogiri/XMLNode",
|
52
|
+
{
|
53
|
+
(gc_callback_t)_xml_node_mark, (gc_callback_t)_xml_node_dealloc, 0,
|
54
|
+
#ifdef HAVE_RB_GC_LOCATION
|
55
|
+
(gc_callback_t)_xml_node_update_references
|
56
|
+
#endif
|
57
|
+
},
|
58
|
+
0, 0,
|
59
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
60
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
61
|
+
#endif
|
62
|
+
};
|
63
|
+
|
64
|
+
static void
|
65
|
+
relink_namespace(xmlNodePtr reparented)
|
32
66
|
{
|
33
67
|
xmlNodePtr child;
|
68
|
+
xmlAttrPtr attr;
|
34
69
|
|
35
70
|
if (reparented->type != XML_ATTRIBUTE_NODE &&
|
36
71
|
reparented->type != XML_ELEMENT_NODE) { return; }
|
@@ -42,7 +77,7 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
42
77
|
name = xmlSplitQName2(reparented->name, &prefix);
|
43
78
|
|
44
79
|
if (reparented->type == XML_ATTRIBUTE_NODE) {
|
45
|
-
if (prefix == NULL || strcmp((char*)prefix, XMLNS_PREFIX) == 0) {
|
80
|
+
if (prefix == NULL || strcmp((char *)prefix, XMLNS_PREFIX) == 0) {
|
46
81
|
xmlFree(name);
|
47
82
|
xmlFree(prefix);
|
48
83
|
return;
|
@@ -64,7 +99,9 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
64
99
|
if (reparented->type != XML_ELEMENT_NODE || !reparented->parent) { return; }
|
65
100
|
|
66
101
|
/* Make sure that our reparented node has the correct namespaces */
|
67
|
-
if (!reparented->ns &&
|
102
|
+
if (!reparented->ns &&
|
103
|
+
(reparented->doc != (xmlDocPtr)reparented->parent) &&
|
104
|
+
(rb_iv_get(DOC_RUBY_OBJECT(reparented->doc), "@namespace_inheritance") == Qtrue)) {
|
68
105
|
xmlSetNs(reparented, reparented->parent->ns);
|
69
106
|
}
|
70
107
|
|
@@ -87,7 +124,7 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
87
124
|
} else {
|
88
125
|
reparented->nsDef = curr->next;
|
89
126
|
}
|
90
|
-
|
127
|
+
noko_xml_document_pin_namespace(curr, reparented->doc);
|
91
128
|
} else {
|
92
129
|
prev = curr;
|
93
130
|
}
|
@@ -127,16 +164,19 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
127
164
|
}
|
128
165
|
|
129
166
|
if (reparented->type == XML_ELEMENT_NODE) {
|
130
|
-
|
131
|
-
while(NULL !=
|
132
|
-
relink_namespace(
|
133
|
-
|
167
|
+
attr = reparented->properties;
|
168
|
+
while (NULL != attr) {
|
169
|
+
relink_namespace((xmlNodePtr)attr);
|
170
|
+
attr = attr->next;
|
134
171
|
}
|
135
172
|
}
|
136
173
|
}
|
137
174
|
|
138
|
-
|
139
|
-
|
175
|
+
|
176
|
+
/* internal function meant to wrap xmlReplaceNode
|
177
|
+
and fix some issues we have with libxml2 merging nodes */
|
178
|
+
static xmlNodePtr
|
179
|
+
xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
|
140
180
|
{
|
141
181
|
xmlNodePtr retval ;
|
142
182
|
|
@@ -159,22 +199,34 @@ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
|
|
159
199
|
return retval ;
|
160
200
|
}
|
161
201
|
|
162
|
-
|
163
|
-
static
|
202
|
+
|
203
|
+
static void
|
204
|
+
raise_if_ancestor_of_self(xmlNodePtr self)
|
205
|
+
{
|
206
|
+
for (xmlNodePtr ancestor = self->parent ; ancestor ; ancestor = ancestor->parent) {
|
207
|
+
if (self == ancestor) {
|
208
|
+
rb_raise(rb_eRuntimeError, "cycle detected: node '%s' is an ancestor of itself", self->name);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
|
214
|
+
static VALUE
|
215
|
+
reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
|
164
216
|
{
|
165
217
|
VALUE reparented_obj ;
|
166
|
-
xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text, parent ;
|
218
|
+
xmlNodePtr reparentee, original_reparentee, pivot, reparented, next_text, new_next_text, parent ;
|
167
219
|
int original_ns_prefix_is_default = 0 ;
|
168
220
|
|
169
|
-
if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
|
221
|
+
if (!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
|
170
222
|
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
|
171
223
|
}
|
172
|
-
if(rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
|
224
|
+
if (rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
|
173
225
|
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
|
174
226
|
}
|
175
227
|
|
176
|
-
|
177
|
-
|
228
|
+
Noko_Node_Get_Struct(reparentee_obj, xmlNode, reparentee);
|
229
|
+
Noko_Node_Get_Struct(pivot_obj, xmlNode, pivot);
|
178
230
|
|
179
231
|
/*
|
180
232
|
* Check if nodes given are appropriate to have a parent-child
|
@@ -190,66 +242,66 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
|
|
190
242
|
|
191
243
|
if (parent) {
|
192
244
|
switch (parent->type) {
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
245
|
+
case XML_DOCUMENT_NODE:
|
246
|
+
case XML_HTML_DOCUMENT_NODE:
|
247
|
+
switch (reparentee->type) {
|
248
|
+
case XML_ELEMENT_NODE:
|
249
|
+
case XML_PI_NODE:
|
250
|
+
case XML_COMMENT_NODE:
|
251
|
+
case XML_DOCUMENT_TYPE_NODE:
|
252
|
+
/*
|
253
|
+
* The DOM specification says no to adding text-like nodes
|
254
|
+
* directly to a document, but we allow it for compatibility.
|
255
|
+
*/
|
256
|
+
case XML_TEXT_NODE:
|
257
|
+
case XML_CDATA_SECTION_NODE:
|
258
|
+
case XML_ENTITY_REF_NODE:
|
259
|
+
goto ok;
|
260
|
+
default:
|
261
|
+
break;
|
262
|
+
}
|
209
263
|
break;
|
210
|
-
|
211
|
-
break;
|
212
|
-
case XML_DOCUMENT_FRAG_NODE:
|
213
|
-
case XML_ENTITY_REF_NODE:
|
214
|
-
case XML_ELEMENT_NODE:
|
215
|
-
switch (reparentee->type) {
|
216
|
-
case XML_ELEMENT_NODE:
|
217
|
-
case XML_PI_NODE:
|
218
|
-
case XML_COMMENT_NODE:
|
219
|
-
case XML_TEXT_NODE:
|
220
|
-
case XML_CDATA_SECTION_NODE:
|
264
|
+
case XML_DOCUMENT_FRAG_NODE:
|
221
265
|
case XML_ENTITY_REF_NODE:
|
222
|
-
|
223
|
-
|
266
|
+
case XML_ELEMENT_NODE:
|
267
|
+
switch (reparentee->type) {
|
268
|
+
case XML_ELEMENT_NODE:
|
269
|
+
case XML_PI_NODE:
|
270
|
+
case XML_COMMENT_NODE:
|
271
|
+
case XML_TEXT_NODE:
|
272
|
+
case XML_CDATA_SECTION_NODE:
|
273
|
+
case XML_ENTITY_REF_NODE:
|
274
|
+
goto ok;
|
275
|
+
default:
|
276
|
+
break;
|
277
|
+
}
|
278
|
+
break;
|
279
|
+
case XML_ATTRIBUTE_NODE:
|
280
|
+
switch (reparentee->type) {
|
281
|
+
case XML_TEXT_NODE:
|
282
|
+
case XML_ENTITY_REF_NODE:
|
283
|
+
goto ok;
|
284
|
+
default:
|
285
|
+
break;
|
286
|
+
}
|
224
287
|
break;
|
225
|
-
}
|
226
|
-
break;
|
227
|
-
case XML_ATTRIBUTE_NODE:
|
228
|
-
switch (reparentee->type) {
|
229
288
|
case XML_TEXT_NODE:
|
230
|
-
|
231
|
-
|
289
|
+
/*
|
290
|
+
* xmlAddChild() breaks the DOM specification in that it allows
|
291
|
+
* adding a text node to another, in which case text nodes are
|
292
|
+
* coalesced, but since our JRuby version does not support such
|
293
|
+
* operation, we should inhibit it.
|
294
|
+
*/
|
295
|
+
break;
|
232
296
|
default:
|
233
297
|
break;
|
234
|
-
}
|
235
|
-
break;
|
236
|
-
case XML_TEXT_NODE:
|
237
|
-
/*
|
238
|
-
* xmlAddChild() breaks the DOM specification in that it allows
|
239
|
-
* adding a text node to another, in which case text nodes are
|
240
|
-
* coalesced, but since our JRuby version does not support such
|
241
|
-
* operation, we should inhibit it.
|
242
|
-
*/
|
243
|
-
break;
|
244
|
-
default:
|
245
|
-
break;
|
246
298
|
}
|
247
299
|
|
248
300
|
rb_raise(rb_eArgError, "cannot reparent %s there", rb_obj_classname(reparentee_obj));
|
249
301
|
}
|
250
302
|
|
251
303
|
ok:
|
252
|
-
|
304
|
+
original_reparentee = reparentee;
|
253
305
|
|
254
306
|
if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
|
255
307
|
/*
|
@@ -290,7 +342,7 @@ ok:
|
|
290
342
|
original_ns_prefix_is_default = 1;
|
291
343
|
}
|
292
344
|
|
293
|
-
|
345
|
+
noko_xml_document_pin_node(reparentee);
|
294
346
|
|
295
347
|
if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
|
296
348
|
rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
|
@@ -301,11 +353,13 @@ ok:
|
|
301
353
|
* issue #391, where new node's prefix may become the string "default"
|
302
354
|
* see libxml2 tree.c xmlNewReconciliedNs which implements this behavior.
|
303
355
|
*/
|
304
|
-
xmlFree(reparentee->ns->prefix);
|
356
|
+
xmlFree(DISCARD_CONST_QUAL_XMLCHAR(reparentee->ns->prefix));
|
305
357
|
reparentee->ns->prefix = NULL;
|
306
358
|
}
|
307
359
|
}
|
308
360
|
|
361
|
+
xmlUnlinkNode(original_reparentee);
|
362
|
+
|
309
363
|
if (prf != xmlAddPrevSibling && prf != xmlAddNextSibling
|
310
364
|
&& reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
|
311
365
|
/*
|
@@ -330,12 +384,12 @@ ok:
|
|
330
384
|
new_next_text = xmlDocCopyNode(next_text, pivot->doc, 1) ;
|
331
385
|
|
332
386
|
xmlUnlinkNode(next_text);
|
333
|
-
|
387
|
+
noko_xml_document_pin_node(next_text);
|
334
388
|
|
335
389
|
xmlAddNextSibling(pivot, new_next_text);
|
336
390
|
}
|
337
391
|
|
338
|
-
if(!(reparented = (*prf)(pivot, reparentee))) {
|
392
|
+
if (!(reparented = (*prf)(pivot, reparentee))) {
|
339
393
|
rb_raise(rb_eRuntimeError, "Could not reparent node");
|
340
394
|
}
|
341
395
|
|
@@ -345,57 +399,432 @@ ok:
|
|
345
399
|
* adjacent text nodes.
|
346
400
|
*/
|
347
401
|
DATA_PTR(reparentee_obj) = reparented ;
|
402
|
+
reparented_obj = noko_xml_node_wrap(Qnil, reparented);
|
348
403
|
|
349
|
-
|
404
|
+
rb_funcall(reparented_obj, id_decorate_bang, 0);
|
350
405
|
|
351
|
-
|
406
|
+
/* if we've created a cycle, raise an exception */
|
407
|
+
raise_if_ancestor_of_self(reparented);
|
352
408
|
|
353
|
-
|
409
|
+
relink_namespace(reparented);
|
354
410
|
|
355
411
|
return reparented_obj ;
|
356
412
|
}
|
357
413
|
|
414
|
+
// :startdoc:
|
358
415
|
|
359
416
|
/*
|
360
|
-
* call-seq:
|
361
|
-
*
|
417
|
+
* :call-seq:
|
418
|
+
* add_namespace_definition(prefix, href) → Nokogiri::XML::Namespace
|
419
|
+
* add_namespace(prefix, href) → Nokogiri::XML::Namespace
|
420
|
+
*
|
421
|
+
* :category: Manipulating Document Structure
|
422
|
+
*
|
423
|
+
* Adds a namespace definition to this node with +prefix+ using +href+ value, as if this node had
|
424
|
+
* included an attribute "xmlns:prefix=href".
|
425
|
+
*
|
426
|
+
* A default namespace definition for this node can be added by passing +nil+ for +prefix+.
|
427
|
+
*
|
428
|
+
* [Parameters]
|
429
|
+
* - +prefix+ (String, +nil+) An {XML Name}[https://www.w3.org/TR/xml-names/#ns-decl]
|
430
|
+
* - +href+ (String) The {URI reference}[https://www.w3.org/TR/xml-names/#sec-namespaces]
|
431
|
+
*
|
432
|
+
* [Returns] The new Nokogiri::XML::Namespace
|
433
|
+
*
|
434
|
+
* *Example:* adding a non-default namespace definition
|
435
|
+
*
|
436
|
+
* doc = Nokogiri::XML("<store><inventory></inventory></store>")
|
437
|
+
* inventory = doc.at_css("inventory")
|
438
|
+
* inventory.add_namespace_definition("automobile", "http://alices-autos.com/")
|
439
|
+
* inventory.add_namespace_definition("bicycle", "http://bobs-bikes.com/")
|
440
|
+
* inventory.add_child("<automobile:tire>Michelin model XGV, size 75R</automobile:tire>")
|
441
|
+
* doc.to_xml
|
442
|
+
* # => "<?xml version=\"1.0\"?>\n" +
|
443
|
+
* # "<store>\n" +
|
444
|
+
* # " <inventory xmlns:automobile=\"http://alices-autos.com/\" xmlns:bicycle=\"http://bobs-bikes.com/\">\n" +
|
445
|
+
* # " <automobile:tire>Michelin model XGV, size 75R</automobile:tire>\n" +
|
446
|
+
* # " </inventory>\n" +
|
447
|
+
* # "</store>\n"
|
448
|
+
*
|
449
|
+
* *Example:* adding a default namespace definition
|
450
|
+
*
|
451
|
+
* doc = Nokogiri::XML("<store><inventory><tire>Michelin model XGV, size 75R</tire></inventory></store>")
|
452
|
+
* doc.at_css("tire").add_namespace_definition(nil, "http://bobs-bikes.com/")
|
453
|
+
* doc.to_xml
|
454
|
+
* # => "<?xml version=\"1.0\"?>\n" +
|
455
|
+
* # "<store>\n" +
|
456
|
+
* # " <inventory>\n" +
|
457
|
+
* # " <tire xmlns=\"http://bobs-bikes.com/\">Michelin model XGV, size 75R</tire>\n" +
|
458
|
+
* # " </inventory>\n" +
|
459
|
+
* # "</store>\n"
|
460
|
+
*
|
461
|
+
*/
|
462
|
+
static VALUE
|
463
|
+
rb_xml_node_add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
|
464
|
+
{
|
465
|
+
xmlNodePtr c_node, element;
|
466
|
+
xmlNsPtr c_namespace;
|
467
|
+
const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
|
468
|
+
|
469
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
470
|
+
element = c_node ;
|
471
|
+
|
472
|
+
c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
|
473
|
+
|
474
|
+
if (!c_namespace) {
|
475
|
+
if (c_node->type != XML_ELEMENT_NODE) {
|
476
|
+
element = c_node->parent;
|
477
|
+
}
|
478
|
+
c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
|
479
|
+
}
|
480
|
+
|
481
|
+
if (!c_namespace) {
|
482
|
+
return Qnil ;
|
483
|
+
}
|
484
|
+
|
485
|
+
if (NIL_P(rb_prefix) || c_node != element) {
|
486
|
+
xmlSetNs(c_node, c_namespace);
|
487
|
+
}
|
488
|
+
|
489
|
+
return noko_xml_namespace_wrap(c_namespace, c_node->doc);
|
490
|
+
}
|
491
|
+
|
492
|
+
|
493
|
+
/*
|
494
|
+
* :call-seq: attribute(name) → Nokogiri::XML::Attr
|
495
|
+
*
|
496
|
+
* :category: Working With Node Attributes
|
497
|
+
*
|
498
|
+
* [Returns] Attribute (Nokogiri::XML::Attr) belonging to this node with name +name+.
|
499
|
+
*
|
500
|
+
* ⚠ Note that attribute namespaces are ignored and only the simple (non-namespace-prefixed) name is
|
501
|
+
* used to find a matching attribute. In case of a simple name collision, only one of the matching
|
502
|
+
* attributes will be returned. In this case, you will need to use #attribute_with_ns.
|
503
|
+
*
|
504
|
+
* *Example:*
|
505
|
+
*
|
506
|
+
* doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
|
507
|
+
* child = doc.at_css("child")
|
508
|
+
* child.attribute("size") # => #<Nokogiri::XML::Attr:0x550 name="size" value="large">
|
509
|
+
* child.attribute("class") # => #<Nokogiri::XML::Attr:0x564 name="class" value="big wide tall">
|
510
|
+
*
|
511
|
+
* *Example* showing that namespaced attributes will not be returned:
|
512
|
+
*
|
513
|
+
* ⚠ Note that only one of the two matching attributes is returned.
|
514
|
+
*
|
515
|
+
* doc = Nokogiri::XML(<<~EOF)
|
516
|
+
* <root xmlns:width='http://example.com/widths'
|
517
|
+
* xmlns:height='http://example.com/heights'>
|
518
|
+
* <child width:size='broad' height:size='tall'/>
|
519
|
+
* </root>
|
520
|
+
* EOF
|
521
|
+
* doc.at_css("child").attribute("size")
|
522
|
+
* # => #(Attr:0x550 {
|
523
|
+
* # name = "size",
|
524
|
+
* # namespace = #(Namespace:0x564 {
|
525
|
+
* # prefix = "width",
|
526
|
+
* # href = "http://example.com/widths"
|
527
|
+
* # }),
|
528
|
+
* # value = "broad"
|
529
|
+
* # })
|
530
|
+
*/
|
531
|
+
static VALUE
|
532
|
+
rb_xml_node_attribute(VALUE self, VALUE name)
|
533
|
+
{
|
534
|
+
xmlNodePtr node;
|
535
|
+
xmlAttrPtr prop;
|
536
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
537
|
+
prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
|
538
|
+
|
539
|
+
if (! prop) { return Qnil; }
|
540
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
|
541
|
+
}
|
542
|
+
|
543
|
+
|
544
|
+
/*
|
545
|
+
* :call-seq: attribute_nodes() → Array<Nokogiri::XML::Attr>
|
546
|
+
*
|
547
|
+
* :category: Working With Node Attributes
|
548
|
+
*
|
549
|
+
* [Returns] Attributes (an Array of Nokogiri::XML::Attr) belonging to this node.
|
550
|
+
*
|
551
|
+
* Note that this is the preferred alternative to #attributes when the simple
|
552
|
+
* (non-namespace-prefixed) attribute names may collide.
|
553
|
+
*
|
554
|
+
* *Example:*
|
555
|
+
*
|
556
|
+
* Contrast this with the colliding-name example from #attributes.
|
557
|
+
*
|
558
|
+
* doc = Nokogiri::XML(<<~EOF)
|
559
|
+
* <root xmlns:width='http://example.com/widths'
|
560
|
+
* xmlns:height='http://example.com/heights'>
|
561
|
+
* <child width:size='broad' height:size='tall'/>
|
562
|
+
* </root>
|
563
|
+
* EOF
|
564
|
+
* doc.at_css("child").attribute_nodes
|
565
|
+
* # => [#(Attr:0x550 {
|
566
|
+
* # name = "size",
|
567
|
+
* # namespace = #(Namespace:0x564 {
|
568
|
+
* # prefix = "width",
|
569
|
+
* # href = "http://example.com/widths"
|
570
|
+
* # }),
|
571
|
+
* # value = "broad"
|
572
|
+
* # }),
|
573
|
+
* # #(Attr:0x578 {
|
574
|
+
* # name = "size",
|
575
|
+
* # namespace = #(Namespace:0x58c {
|
576
|
+
* # prefix = "height",
|
577
|
+
* # href = "http://example.com/heights"
|
578
|
+
* # }),
|
579
|
+
* # value = "tall"
|
580
|
+
* # })]
|
581
|
+
*/
|
582
|
+
static VALUE
|
583
|
+
rb_xml_node_attribute_nodes(VALUE rb_node)
|
584
|
+
{
|
585
|
+
xmlNodePtr c_node;
|
586
|
+
|
587
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
588
|
+
|
589
|
+
return noko_xml_node_attrs(c_node);
|
590
|
+
}
|
591
|
+
|
592
|
+
|
593
|
+
/*
|
594
|
+
* :call-seq: attribute_with_ns(name, namespace) → Nokogiri::XML::Attr
|
595
|
+
*
|
596
|
+
* :category: Working With Node Attributes
|
597
|
+
*
|
598
|
+
* [Returns]
|
599
|
+
* Attribute (Nokogiri::XML::Attr) belonging to this node with matching +name+ and +namespace+.
|
600
|
+
*
|
601
|
+
* [Parameters]
|
602
|
+
* - +name+ (String): the simple (non-namespace-prefixed) name of the attribute
|
603
|
+
* - +namespace+ (String): the URI of the attribute's namespace
|
604
|
+
*
|
605
|
+
* See related: #attribute
|
606
|
+
*
|
607
|
+
* *Example:*
|
608
|
+
*
|
609
|
+
* doc = Nokogiri::XML(<<~EOF)
|
610
|
+
* <root xmlns:width='http://example.com/widths'
|
611
|
+
* xmlns:height='http://example.com/heights'>
|
612
|
+
* <child width:size='broad' height:size='tall'/>
|
613
|
+
* </root>
|
614
|
+
* EOF
|
615
|
+
* doc.at_css("child").attribute_with_ns("size", "http://example.com/widths")
|
616
|
+
* # => #(Attr:0x550 {
|
617
|
+
* # name = "size",
|
618
|
+
* # namespace = #(Namespace:0x564 {
|
619
|
+
* # prefix = "width",
|
620
|
+
* # href = "http://example.com/widths"
|
621
|
+
* # }),
|
622
|
+
* # value = "broad"
|
623
|
+
* # })
|
624
|
+
* doc.at_css("child").attribute_with_ns("size", "http://example.com/heights")
|
625
|
+
* # => #(Attr:0x578 {
|
626
|
+
* # name = "size",
|
627
|
+
* # namespace = #(Namespace:0x58c {
|
628
|
+
* # prefix = "height",
|
629
|
+
* # href = "http://example.com/heights"
|
630
|
+
* # }),
|
631
|
+
* # value = "tall"
|
632
|
+
* # })
|
633
|
+
*/
|
634
|
+
static VALUE
|
635
|
+
rb_xml_node_attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
|
636
|
+
{
|
637
|
+
xmlNodePtr node;
|
638
|
+
xmlAttrPtr prop;
|
639
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
640
|
+
prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
|
641
|
+
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
|
642
|
+
|
643
|
+
if (! prop) { return Qnil; }
|
644
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
|
645
|
+
}
|
646
|
+
|
647
|
+
|
648
|
+
|
649
|
+
/*
|
650
|
+
* call-seq: blank? → Boolean
|
651
|
+
*
|
652
|
+
* [Returns] +true+ if the node is an empty or whitespace-only text or cdata node, else +false+.
|
653
|
+
*
|
654
|
+
* *Example:*
|
655
|
+
*
|
656
|
+
* Nokogiri("<root><child/></root>").root.child.blank? # => false
|
657
|
+
* Nokogiri("<root>\t \n</root>").root.child.blank? # => true
|
658
|
+
* Nokogiri("<root><![CDATA[\t \n]]></root>").root.child.blank? # => true
|
659
|
+
* Nokogiri("<root>not-blank</root>").root.child
|
660
|
+
* .tap { |n| n.content = "" }.blank # => true
|
661
|
+
*/
|
662
|
+
static VALUE
|
663
|
+
rb_xml_node_blank_eh(VALUE self)
|
664
|
+
{
|
665
|
+
xmlNodePtr node;
|
666
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
667
|
+
return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
|
668
|
+
}
|
669
|
+
|
670
|
+
|
671
|
+
/*
|
672
|
+
* :call-seq: child() → Nokogiri::XML::Node
|
673
|
+
*
|
674
|
+
* :category: Traversing Document Structure
|
675
|
+
*
|
676
|
+
* [Returns] First of this node's children, or +nil+ if there are no children
|
677
|
+
*
|
678
|
+
* This is a convenience method and is equivalent to:
|
679
|
+
*
|
680
|
+
* node.children.first
|
681
|
+
*
|
682
|
+
* See related: #children
|
683
|
+
*/
|
684
|
+
static VALUE
|
685
|
+
rb_xml_node_child(VALUE self)
|
686
|
+
{
|
687
|
+
xmlNodePtr node, child;
|
688
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
689
|
+
|
690
|
+
child = node->children;
|
691
|
+
if (!child) { return Qnil; }
|
692
|
+
|
693
|
+
return noko_xml_node_wrap(Qnil, child);
|
694
|
+
}
|
695
|
+
|
696
|
+
|
697
|
+
/*
|
698
|
+
* :call-seq: children() → Nokogiri::XML::NodeSet
|
699
|
+
*
|
700
|
+
* :category: Traversing Document Structure
|
701
|
+
*
|
702
|
+
* [Returns] Nokogiri::XML::NodeSet containing this node's children.
|
703
|
+
*/
|
704
|
+
static VALUE
|
705
|
+
rb_xml_node_children(VALUE self)
|
706
|
+
{
|
707
|
+
xmlNodePtr node;
|
708
|
+
xmlNodePtr child;
|
709
|
+
xmlNodeSetPtr set;
|
710
|
+
VALUE document;
|
711
|
+
VALUE node_set;
|
712
|
+
|
713
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
714
|
+
|
715
|
+
child = node->children;
|
716
|
+
set = xmlXPathNodeSetCreate(child);
|
717
|
+
|
718
|
+
document = DOC_RUBY_OBJECT(node->doc);
|
719
|
+
|
720
|
+
if (!child) { return noko_xml_node_set_wrap(set, document); }
|
721
|
+
|
722
|
+
child = child->next;
|
723
|
+
while (NULL != child) {
|
724
|
+
xmlXPathNodeSetAddUnique(set, child);
|
725
|
+
child = child->next;
|
726
|
+
}
|
727
|
+
|
728
|
+
node_set = noko_xml_node_set_wrap(set, document);
|
729
|
+
|
730
|
+
return node_set;
|
731
|
+
}
|
732
|
+
|
733
|
+
|
734
|
+
/*
|
735
|
+
* :call-seq:
|
736
|
+
* content() → String
|
737
|
+
* inner_text() → String
|
738
|
+
* text() → String
|
739
|
+
* to_str() → String
|
740
|
+
*
|
741
|
+
* [Returns]
|
742
|
+
* Contents of all the text nodes in this node's subtree, concatenated together into a single
|
743
|
+
* String.
|
744
|
+
*
|
745
|
+
* ⚠ Note that entities will _always_ be expanded in the returned String.
|
362
746
|
*
|
363
|
-
*
|
747
|
+
* See related: #inner_html
|
748
|
+
*
|
749
|
+
* *Example* of how entities are handled:
|
750
|
+
*
|
751
|
+
* Note that <tt><</tt> becomes <tt><</tt> in the returned String.
|
752
|
+
*
|
753
|
+
* doc = Nokogiri::XML.fragment("<child>a < b</child>")
|
754
|
+
* doc.at_css("child").content
|
755
|
+
* # => "a < b"
|
756
|
+
*
|
757
|
+
* *Example* of how a subtree is handled:
|
758
|
+
*
|
759
|
+
* Note that the <tt><span></tt> tags are omitted and only the text node contents are returned,
|
760
|
+
* concatenated into a single string.
|
761
|
+
*
|
762
|
+
* doc = Nokogiri::XML.fragment("<child><span>first</span> <span>second</span></child>")
|
763
|
+
* doc.at_css("child").content
|
764
|
+
* # => "first second"
|
364
765
|
*/
|
365
|
-
static VALUE
|
766
|
+
static VALUE
|
767
|
+
rb_xml_node_content(VALUE self)
|
366
768
|
{
|
367
769
|
xmlNodePtr node;
|
368
|
-
|
770
|
+
xmlChar *content;
|
771
|
+
|
772
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
773
|
+
|
774
|
+
content = xmlNodeGetContent(node);
|
775
|
+
if (content) {
|
776
|
+
VALUE rval = NOKOGIRI_STR_NEW2(content);
|
777
|
+
xmlFree(content);
|
778
|
+
return rval;
|
779
|
+
}
|
780
|
+
return Qnil;
|
781
|
+
}
|
782
|
+
|
783
|
+
|
784
|
+
/*
|
785
|
+
* :call-seq: document() → Nokogiri::XML::Document
|
786
|
+
*
|
787
|
+
* :category: Traversing Document Structure
|
788
|
+
*
|
789
|
+
* [Returns] Parent Nokogiri::XML::Document for this node
|
790
|
+
*/
|
791
|
+
static VALUE
|
792
|
+
rb_xml_node_document(VALUE self)
|
793
|
+
{
|
794
|
+
xmlNodePtr node;
|
795
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
369
796
|
return DOC_RUBY_OBJECT(node->doc);
|
370
797
|
}
|
371
798
|
|
372
799
|
/*
|
373
|
-
* call-seq:
|
374
|
-
* pointer_id
|
800
|
+
* :call-seq: pointer_id() → Integer
|
375
801
|
*
|
376
|
-
*
|
802
|
+
* [Returns]
|
803
|
+
* A unique id for this node based on the internal memory structures. This method is used by #==
|
804
|
+
* to determine node identity.
|
377
805
|
*/
|
378
|
-
static VALUE
|
806
|
+
static VALUE
|
807
|
+
rb_xml_node_pointer_id(VALUE self)
|
379
808
|
{
|
380
809
|
xmlNodePtr node;
|
381
|
-
|
810
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
382
811
|
|
383
812
|
return INT2NUM((long)(node));
|
384
813
|
}
|
385
814
|
|
386
815
|
/*
|
387
|
-
* call-seq:
|
388
|
-
* encode_special_chars(string)
|
816
|
+
* :call-seq: encode_special_chars(string) → String
|
389
817
|
*
|
390
818
|
* Encode any special characters in +string+
|
391
819
|
*/
|
392
|
-
static VALUE
|
820
|
+
static VALUE
|
821
|
+
encode_special_chars(VALUE self, VALUE string)
|
393
822
|
{
|
394
823
|
xmlNodePtr node;
|
395
824
|
xmlChar *encoded;
|
396
825
|
VALUE encoded_str;
|
397
826
|
|
398
|
-
|
827
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
399
828
|
encoded = xmlEncodeSpecialChars(
|
400
829
|
node->doc,
|
401
830
|
(const xmlChar *)StringValueCStr(string)
|
@@ -408,8 +837,8 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
|
|
408
837
|
}
|
409
838
|
|
410
839
|
/*
|
411
|
-
* call-seq:
|
412
|
-
*
|
840
|
+
* :call-seq:
|
841
|
+
* create_internal_subset(name, external_id, system_id)
|
413
842
|
*
|
414
843
|
* Create the internal subset of a document.
|
415
844
|
*
|
@@ -419,17 +848,18 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
|
|
419
848
|
* doc.create_internal_subset("chapter", nil, "chapter.dtd")
|
420
849
|
* # => <!DOCTYPE chapter SYSTEM "chapter.dtd">
|
421
850
|
*/
|
422
|
-
static VALUE
|
851
|
+
static VALUE
|
852
|
+
create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
|
423
853
|
{
|
424
854
|
xmlNodePtr node;
|
425
855
|
xmlDocPtr doc;
|
426
856
|
xmlDtdPtr dtd;
|
427
857
|
|
428
|
-
|
858
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
429
859
|
|
430
860
|
doc = node->doc;
|
431
861
|
|
432
|
-
if(xmlGetIntSubset(doc)) {
|
862
|
+
if (xmlGetIntSubset(doc)) {
|
433
863
|
rb_raise(rb_eRuntimeError, "Document already has an internal subset");
|
434
864
|
}
|
435
865
|
|
@@ -440,28 +870,29 @@ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, V
|
|
440
870
|
NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
|
441
871
|
);
|
442
872
|
|
443
|
-
if(!dtd) { return Qnil; }
|
873
|
+
if (!dtd) { return Qnil; }
|
444
874
|
|
445
|
-
return
|
875
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
446
876
|
}
|
447
877
|
|
448
878
|
/*
|
449
|
-
* call-seq:
|
450
|
-
*
|
879
|
+
* :call-seq:
|
880
|
+
* create_external_subset(name, external_id, system_id)
|
451
881
|
*
|
452
882
|
* Create an external subset
|
453
883
|
*/
|
454
|
-
static VALUE
|
884
|
+
static VALUE
|
885
|
+
create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
|
455
886
|
{
|
456
887
|
xmlNodePtr node;
|
457
888
|
xmlDocPtr doc;
|
458
889
|
xmlDtdPtr dtd;
|
459
890
|
|
460
|
-
|
891
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
461
892
|
|
462
893
|
doc = node->doc;
|
463
894
|
|
464
|
-
if(doc->extSubset) {
|
895
|
+
if (doc->extSubset) {
|
465
896
|
rb_raise(rb_eRuntimeError, "Document already has an external subset");
|
466
897
|
}
|
467
898
|
|
@@ -472,72 +903,78 @@ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, V
|
|
472
903
|
NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
|
473
904
|
);
|
474
905
|
|
475
|
-
if(!dtd) { return Qnil; }
|
906
|
+
if (!dtd) { return Qnil; }
|
476
907
|
|
477
|
-
return
|
908
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
478
909
|
}
|
479
910
|
|
480
911
|
/*
|
481
|
-
* call-seq:
|
482
|
-
*
|
912
|
+
* :call-seq:
|
913
|
+
* external_subset()
|
483
914
|
*
|
484
915
|
* Get the external subset
|
485
916
|
*/
|
486
|
-
static VALUE
|
917
|
+
static VALUE
|
918
|
+
external_subset(VALUE self)
|
487
919
|
{
|
488
920
|
xmlNodePtr node;
|
489
921
|
xmlDocPtr doc;
|
490
922
|
xmlDtdPtr dtd;
|
491
923
|
|
492
|
-
|
924
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
493
925
|
|
494
|
-
if(!node->doc) { return Qnil; }
|
926
|
+
if (!node->doc) { return Qnil; }
|
495
927
|
|
496
928
|
doc = node->doc;
|
497
929
|
dtd = doc->extSubset;
|
498
930
|
|
499
|
-
if(!dtd) { return Qnil; }
|
931
|
+
if (!dtd) { return Qnil; }
|
500
932
|
|
501
|
-
return
|
933
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
502
934
|
}
|
503
935
|
|
504
936
|
/*
|
505
|
-
* call-seq:
|
506
|
-
*
|
937
|
+
* :call-seq:
|
938
|
+
* internal_subset()
|
507
939
|
*
|
508
940
|
* Get the internal subset
|
509
941
|
*/
|
510
|
-
static VALUE
|
942
|
+
static VALUE
|
943
|
+
internal_subset(VALUE self)
|
511
944
|
{
|
512
945
|
xmlNodePtr node;
|
513
946
|
xmlDocPtr doc;
|
514
947
|
xmlDtdPtr dtd;
|
515
948
|
|
516
|
-
|
949
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
517
950
|
|
518
|
-
if(!node->doc) { return Qnil; }
|
951
|
+
if (!node->doc) { return Qnil; }
|
519
952
|
|
520
953
|
doc = node->doc;
|
521
954
|
dtd = xmlGetIntSubset(doc);
|
522
955
|
|
523
|
-
if(!dtd) { return Qnil; }
|
956
|
+
if (!dtd) { return Qnil; }
|
524
957
|
|
525
|
-
return
|
958
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
526
959
|
}
|
527
960
|
|
528
961
|
/*
|
529
|
-
* call-seq:
|
530
|
-
*
|
531
|
-
*
|
532
|
-
*
|
962
|
+
* :call-seq:
|
963
|
+
* dup → Nokogiri::XML::Node
|
964
|
+
* dup(depth) → Nokogiri::XML::Node
|
965
|
+
* dup(depth, new_parent_doc) → Nokogiri::XML::Node
|
533
966
|
*
|
534
967
|
* Copy this node.
|
535
|
-
*
|
536
|
-
*
|
537
|
-
*
|
538
|
-
*
|
968
|
+
*
|
969
|
+
* [Parameters]
|
970
|
+
* - +depth+ 0 is a shallow copy, 1 (the default) is a deep copy.
|
971
|
+
* - +new_parent_doc+
|
972
|
+
* The new node's parent Document. Defaults to the this node's document.
|
973
|
+
*
|
974
|
+
* [Returns] The new Nokgiri::XML::Node
|
539
975
|
*/
|
540
|
-
static VALUE
|
976
|
+
static VALUE
|
977
|
+
duplicate_node(int argc, VALUE *argv, VALUE self)
|
541
978
|
{
|
542
979
|
VALUE r_level, r_new_parent_doc;
|
543
980
|
int level;
|
@@ -545,7 +982,7 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
545
982
|
xmlDocPtr new_parent_doc;
|
546
983
|
xmlNodePtr node, dup;
|
547
984
|
|
548
|
-
|
985
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
549
986
|
|
550
987
|
n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
|
551
988
|
|
@@ -561,40 +998,29 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
561
998
|
}
|
562
999
|
|
563
1000
|
dup = xmlDocCopyNode(node, new_parent_doc, level);
|
564
|
-
if(dup == NULL) { return Qnil; }
|
1001
|
+
if (dup == NULL) { return Qnil; }
|
565
1002
|
|
566
|
-
|
1003
|
+
noko_xml_document_pin_node(dup);
|
567
1004
|
|
568
|
-
return
|
1005
|
+
return noko_xml_node_wrap(rb_obj_class(self), dup);
|
569
1006
|
}
|
570
1007
|
|
571
1008
|
/*
|
572
|
-
* call-seq:
|
573
|
-
*
|
1009
|
+
* :call-seq:
|
1010
|
+
* unlink() → self
|
574
1011
|
*
|
575
1012
|
* Unlink this node from its current context.
|
576
1013
|
*/
|
577
|
-
static VALUE
|
1014
|
+
static VALUE
|
1015
|
+
unlink_node(VALUE self)
|
578
1016
|
{
|
579
1017
|
xmlNodePtr node;
|
580
|
-
|
1018
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
581
1019
|
xmlUnlinkNode(node);
|
582
|
-
|
1020
|
+
noko_xml_document_pin_node(node);
|
583
1021
|
return self;
|
584
1022
|
}
|
585
1023
|
|
586
|
-
/*
|
587
|
-
* call-seq:
|
588
|
-
* blank?
|
589
|
-
*
|
590
|
-
* Is this node blank?
|
591
|
-
*/
|
592
|
-
static VALUE blank_eh(VALUE self)
|
593
|
-
{
|
594
|
-
xmlNodePtr node;
|
595
|
-
Data_Get_Struct(self, xmlNode, node);
|
596
|
-
return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
|
597
|
-
}
|
598
1024
|
|
599
1025
|
/*
|
600
1026
|
* call-seq:
|
@@ -602,15 +1028,16 @@ static VALUE blank_eh(VALUE self)
|
|
602
1028
|
*
|
603
1029
|
* Returns the next sibling node
|
604
1030
|
*/
|
605
|
-
static VALUE
|
1031
|
+
static VALUE
|
1032
|
+
next_sibling(VALUE self)
|
606
1033
|
{
|
607
1034
|
xmlNodePtr node, sibling;
|
608
|
-
|
1035
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
609
1036
|
|
610
1037
|
sibling = node->next;
|
611
|
-
if(!sibling) { return Qnil; }
|
1038
|
+
if (!sibling) { return Qnil; }
|
612
1039
|
|
613
|
-
return
|
1040
|
+
return noko_xml_node_wrap(Qnil, sibling) ;
|
614
1041
|
}
|
615
1042
|
|
616
1043
|
/*
|
@@ -619,15 +1046,16 @@ static VALUE next_sibling(VALUE self)
|
|
619
1046
|
*
|
620
1047
|
* Returns the previous sibling node
|
621
1048
|
*/
|
622
|
-
static VALUE
|
1049
|
+
static VALUE
|
1050
|
+
previous_sibling(VALUE self)
|
623
1051
|
{
|
624
1052
|
xmlNodePtr node, sibling;
|
625
|
-
|
1053
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
626
1054
|
|
627
1055
|
sibling = node->prev;
|
628
|
-
if(!sibling) { return Qnil; }
|
1056
|
+
if (!sibling) { return Qnil; }
|
629
1057
|
|
630
|
-
return
|
1058
|
+
return noko_xml_node_wrap(Qnil, sibling);
|
631
1059
|
}
|
632
1060
|
|
633
1061
|
/*
|
@@ -636,15 +1064,16 @@ static VALUE previous_sibling(VALUE self)
|
|
636
1064
|
*
|
637
1065
|
* Returns the next Nokogiri::XML::Element type sibling node.
|
638
1066
|
*/
|
639
|
-
static VALUE
|
1067
|
+
static VALUE
|
1068
|
+
next_element(VALUE self)
|
640
1069
|
{
|
641
1070
|
xmlNodePtr node, sibling;
|
642
|
-
|
1071
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
643
1072
|
|
644
1073
|
sibling = xmlNextElementSibling(node);
|
645
|
-
if(!sibling) { return Qnil; }
|
1074
|
+
if (!sibling) { return Qnil; }
|
646
1075
|
|
647
|
-
return
|
1076
|
+
return noko_xml_node_wrap(Qnil, sibling);
|
648
1077
|
}
|
649
1078
|
|
650
1079
|
/*
|
@@ -653,82 +1082,60 @@ static VALUE next_element(VALUE self)
|
|
653
1082
|
*
|
654
1083
|
* Returns the previous Nokogiri::XML::Element type sibling node.
|
655
1084
|
*/
|
656
|
-
static VALUE
|
1085
|
+
static VALUE
|
1086
|
+
previous_element(VALUE self)
|
657
1087
|
{
|
658
1088
|
xmlNodePtr node, sibling;
|
659
|
-
|
1089
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
660
1090
|
|
661
1091
|
/*
|
662
1092
|
* note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
|
663
1093
|
*/
|
664
1094
|
sibling = node->prev;
|
665
|
-
if(!sibling) { return Qnil; }
|
1095
|
+
if (!sibling) { return Qnil; }
|
666
1096
|
|
667
|
-
while(sibling && sibling->type != XML_ELEMENT_NODE) {
|
1097
|
+
while (sibling && sibling->type != XML_ELEMENT_NODE) {
|
668
1098
|
sibling = sibling->prev;
|
669
1099
|
}
|
670
1100
|
|
671
|
-
return sibling ?
|
1101
|
+
return sibling ? noko_xml_node_wrap(Qnil, sibling) : Qnil ;
|
672
1102
|
}
|
673
1103
|
|
674
1104
|
/* :nodoc: */
|
675
|
-
static VALUE
|
1105
|
+
static VALUE
|
1106
|
+
replace(VALUE self, VALUE new_node)
|
676
1107
|
{
|
677
1108
|
VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
|
678
1109
|
|
679
1110
|
xmlNodePtr pivot;
|
680
|
-
|
681
|
-
|
1111
|
+
Noko_Node_Get_Struct(self, xmlNode, pivot);
|
1112
|
+
noko_xml_document_pin_node(pivot);
|
682
1113
|
|
683
1114
|
return reparent;
|
684
1115
|
}
|
685
1116
|
|
686
1117
|
/*
|
687
|
-
* call-seq:
|
688
|
-
*
|
1118
|
+
* :call-seq:
|
1119
|
+
* element_children() → NodeSet
|
1120
|
+
* elements() → NodeSet
|
689
1121
|
*
|
690
|
-
*
|
691
|
-
|
692
|
-
|
693
|
-
{
|
694
|
-
xmlNodePtr node;
|
695
|
-
xmlNodePtr child;
|
696
|
-
xmlNodeSetPtr set;
|
697
|
-
VALUE document;
|
698
|
-
VALUE node_set;
|
699
|
-
|
700
|
-
Data_Get_Struct(self, xmlNode, node);
|
701
|
-
|
702
|
-
child = node->children;
|
703
|
-
set = xmlXPathNodeSetCreate(child);
|
704
|
-
|
705
|
-
document = DOC_RUBY_OBJECT(node->doc);
|
706
|
-
|
707
|
-
if(!child) { return Nokogiri_wrap_xml_node_set(set, document); }
|
708
|
-
|
709
|
-
child = child->next;
|
710
|
-
while(NULL != child) {
|
711
|
-
xmlXPathNodeSetAddUnique(set, child);
|
712
|
-
child = child->next;
|
713
|
-
}
|
714
|
-
|
715
|
-
node_set = Nokogiri_wrap_xml_node_set(set, document);
|
716
|
-
|
717
|
-
return node_set;
|
718
|
-
}
|
719
|
-
|
720
|
-
/*
|
721
|
-
* call-seq:
|
722
|
-
* element_children
|
1122
|
+
* [Returns]
|
1123
|
+
* The node's child elements as a NodeSet. Only children that are elements will be returned, which
|
1124
|
+
* notably excludes Text nodes.
|
723
1125
|
*
|
724
|
-
*
|
725
|
-
* element nodes.
|
1126
|
+
* *Example:*
|
726
1127
|
*
|
727
|
-
*
|
1128
|
+
* Note that #children returns the Text node "hello" while #element_children does not.
|
728
1129
|
*
|
729
|
-
*
|
1130
|
+
* div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
|
1131
|
+
* div.element_children
|
1132
|
+
* # => [#<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
|
1133
|
+
* div.children
|
1134
|
+
* # => [#<Nokogiri::XML::Text:0x64 "hello">,
|
1135
|
+
* # #<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
|
730
1136
|
*/
|
731
|
-
static VALUE
|
1137
|
+
static VALUE
|
1138
|
+
rb_xml_node_element_children(VALUE self)
|
732
1139
|
{
|
733
1140
|
xmlNodePtr node;
|
734
1141
|
xmlNodePtr child;
|
@@ -736,83 +1143,78 @@ static VALUE element_children(VALUE self)
|
|
736
1143
|
VALUE document;
|
737
1144
|
VALUE node_set;
|
738
1145
|
|
739
|
-
|
1146
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
740
1147
|
|
741
1148
|
child = xmlFirstElementChild(node);
|
742
1149
|
set = xmlXPathNodeSetCreate(child);
|
743
1150
|
|
744
1151
|
document = DOC_RUBY_OBJECT(node->doc);
|
745
1152
|
|
746
|
-
if(!child) { return
|
1153
|
+
if (!child) { return noko_xml_node_set_wrap(set, document); }
|
747
1154
|
|
748
1155
|
child = xmlNextElementSibling(child);
|
749
|
-
while(NULL != child) {
|
1156
|
+
while (NULL != child) {
|
750
1157
|
xmlXPathNodeSetAddUnique(set, child);
|
751
1158
|
child = xmlNextElementSibling(child);
|
752
1159
|
}
|
753
1160
|
|
754
|
-
node_set =
|
1161
|
+
node_set = noko_xml_node_set_wrap(set, document);
|
755
1162
|
|
756
1163
|
return node_set;
|
757
1164
|
}
|
758
1165
|
|
759
1166
|
/*
|
760
|
-
* call-seq:
|
761
|
-
*
|
1167
|
+
* :call-seq:
|
1168
|
+
* first_element_child() → Node
|
762
1169
|
*
|
763
|
-
* Returns
|
764
|
-
*/
|
765
|
-
static VALUE child(VALUE self)
|
766
|
-
{
|
767
|
-
xmlNodePtr node, child;
|
768
|
-
Data_Get_Struct(self, xmlNode, node);
|
769
|
-
|
770
|
-
child = node->children;
|
771
|
-
if(!child) { return Qnil; }
|
772
|
-
|
773
|
-
return Nokogiri_wrap_xml_node(Qnil, child);
|
774
|
-
}
|
775
|
-
|
776
|
-
/*
|
777
|
-
* call-seq:
|
778
|
-
* first_element_child
|
1170
|
+
* [Returns] The first child Node that is an element.
|
779
1171
|
*
|
780
|
-
*
|
1172
|
+
* *Example:*
|
781
1173
|
*
|
782
|
-
*
|
1174
|
+
* Note that the "hello" child, which is a Text node, is skipped and the <tt><span></tt> element is
|
1175
|
+
* returned.
|
783
1176
|
*
|
784
|
-
*
|
1177
|
+
* div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
|
1178
|
+
* div.first_element_child
|
1179
|
+
* # => #(Element:0x3c { name = "span", children = [ #(Text "world")] })
|
785
1180
|
*/
|
786
|
-
static VALUE
|
1181
|
+
static VALUE
|
1182
|
+
rb_xml_node_first_element_child(VALUE self)
|
787
1183
|
{
|
788
1184
|
xmlNodePtr node, child;
|
789
|
-
|
1185
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
790
1186
|
|
791
1187
|
child = xmlFirstElementChild(node);
|
792
|
-
if(!child) { return Qnil; }
|
1188
|
+
if (!child) { return Qnil; }
|
793
1189
|
|
794
|
-
return
|
1190
|
+
return noko_xml_node_wrap(Qnil, child);
|
795
1191
|
}
|
796
1192
|
|
797
1193
|
/*
|
798
|
-
* call-seq:
|
799
|
-
*
|
1194
|
+
* :call-seq:
|
1195
|
+
* last_element_child() → Node
|
1196
|
+
*
|
1197
|
+
* [Returns] The last child Node that is an element.
|
800
1198
|
*
|
801
|
-
*
|
1199
|
+
* *Example:*
|
802
1200
|
*
|
803
|
-
*
|
1201
|
+
* Note that the "hello" child, which is a Text node, is skipped and the <tt><span>yes</span></tt>
|
1202
|
+
* element is returned.
|
804
1203
|
*
|
805
|
-
*
|
1204
|
+
* div = Nokogiri::HTML5("<div><span>no</span><span>yes</span>skip</div>").at_css("div")
|
1205
|
+
* div.last_element_child
|
1206
|
+
* # => #(Element:0x3c { name = "span", children = [ #(Text "yes")] })
|
806
1207
|
*/
|
807
|
-
static VALUE
|
1208
|
+
static VALUE
|
1209
|
+
rb_xml_node_last_element_child(VALUE self)
|
808
1210
|
{
|
809
1211
|
xmlNodePtr node, child;
|
810
|
-
|
1212
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
811
1213
|
|
812
1214
|
child = xmlLastElementChild(node);
|
813
|
-
if(!child) { return Qnil; }
|
1215
|
+
if (!child) { return Qnil; }
|
814
1216
|
|
815
|
-
return
|
1217
|
+
return noko_xml_node_wrap(Qnil, child);
|
816
1218
|
}
|
817
1219
|
|
818
1220
|
/*
|
@@ -821,11 +1223,12 @@ static VALUE last_element_child(VALUE self)
|
|
821
1223
|
*
|
822
1224
|
* Returns true if +attribute+ is set
|
823
1225
|
*/
|
824
|
-
static VALUE
|
1226
|
+
static VALUE
|
1227
|
+
key_eh(VALUE self, VALUE attribute)
|
825
1228
|
{
|
826
1229
|
xmlNodePtr node;
|
827
|
-
|
828
|
-
if(xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
|
1230
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1231
|
+
if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
|
829
1232
|
return Qtrue;
|
830
1233
|
}
|
831
1234
|
return Qfalse;
|
@@ -837,12 +1240,13 @@ static VALUE key_eh(VALUE self, VALUE attribute)
|
|
837
1240
|
*
|
838
1241
|
* Returns true if +attribute+ is set with +namespace+
|
839
1242
|
*/
|
840
|
-
static VALUE
|
1243
|
+
static VALUE
|
1244
|
+
namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
|
841
1245
|
{
|
842
1246
|
xmlNodePtr node;
|
843
|
-
|
844
|
-
if(xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
|
845
|
-
|
1247
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1248
|
+
if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
|
1249
|
+
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
|
846
1250
|
return Qtrue;
|
847
1251
|
}
|
848
1252
|
return Qfalse;
|
@@ -854,11 +1258,12 @@ static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
|
|
854
1258
|
*
|
855
1259
|
* Set the +property+ to +value+
|
856
1260
|
*/
|
857
|
-
static VALUE
|
1261
|
+
static VALUE
|
1262
|
+
set(VALUE self, VALUE property, VALUE value)
|
858
1263
|
{
|
859
1264
|
xmlNodePtr node, cur;
|
860
1265
|
xmlAttrPtr prop;
|
861
|
-
|
1266
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
862
1267
|
|
863
1268
|
/* If a matching attribute node already exists, then xmlSetProp will destroy
|
864
1269
|
* the existing node's children. However, if Nokogiri has a node object
|
@@ -867,13 +1272,13 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
|
|
867
1272
|
* We can avoid this by unlinking these nodes first.
|
868
1273
|
*/
|
869
1274
|
if (node->type != XML_ELEMENT_NODE) {
|
870
|
-
return(Qnil);
|
1275
|
+
return (Qnil);
|
871
1276
|
}
|
872
1277
|
prop = xmlHasProp(node, (xmlChar *)StringValueCStr(property));
|
873
1278
|
if (prop && prop->children) {
|
874
1279
|
for (cur = prop->children; cur; cur = cur->next) {
|
875
1280
|
if (cur->_private) {
|
876
|
-
|
1281
|
+
noko_xml_document_pin_node(cur);
|
877
1282
|
xmlUnlinkNode(cur);
|
878
1283
|
}
|
879
1284
|
}
|
@@ -891,7 +1296,8 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
|
|
891
1296
|
*
|
892
1297
|
* Get the value for +attribute+
|
893
1298
|
*/
|
894
|
-
static VALUE
|
1299
|
+
static VALUE
|
1300
|
+
get(VALUE self, VALUE rattribute)
|
895
1301
|
{
|
896
1302
|
xmlNodePtr node;
|
897
1303
|
xmlChar *value = 0;
|
@@ -902,10 +1308,10 @@ static VALUE get(VALUE self, VALUE rattribute)
|
|
902
1308
|
|
903
1309
|
if (NIL_P(rattribute)) { return Qnil; }
|
904
1310
|
|
905
|
-
|
1311
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
906
1312
|
attribute = xmlCharStrdup(StringValueCStr(rattribute));
|
907
1313
|
|
908
|
-
colon = (
|
1314
|
+
colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
|
909
1315
|
if (colon) {
|
910
1316
|
/* split the attribute string into separate prefix and name by
|
911
1317
|
* null-terminating the prefix at the colon */
|
@@ -917,7 +1323,7 @@ static VALUE get(VALUE self, VALUE rattribute)
|
|
917
1323
|
if (ns) {
|
918
1324
|
value = xmlGetNsProp(node, attr_name, ns->href);
|
919
1325
|
} else {
|
920
|
-
value = xmlGetProp(node, (xmlChar*)StringValueCStr(rattribute));
|
1326
|
+
value = xmlGetProp(node, (xmlChar *)StringValueCStr(rattribute));
|
921
1327
|
}
|
922
1328
|
} else {
|
923
1329
|
value = xmlGetNoNsProp(node, attribute);
|
@@ -938,15 +1344,16 @@ static VALUE get(VALUE self, VALUE rattribute)
|
|
938
1344
|
*
|
939
1345
|
* Set the namespace to +namespace+
|
940
1346
|
*/
|
941
|
-
static VALUE
|
1347
|
+
static VALUE
|
1348
|
+
set_namespace(VALUE self, VALUE namespace)
|
942
1349
|
{
|
943
1350
|
xmlNodePtr node;
|
944
1351
|
xmlNsPtr ns = NULL;
|
945
1352
|
|
946
|
-
|
1353
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
947
1354
|
|
948
|
-
if(!NIL_P(namespace)) {
|
949
|
-
|
1355
|
+
if (!NIL_P(namespace)) {
|
1356
|
+
Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
|
950
1357
|
}
|
951
1358
|
|
952
1359
|
xmlSetNs(node, ns);
|
@@ -955,138 +1362,140 @@ static VALUE set_namespace(VALUE self, VALUE namespace)
|
|
955
1362
|
}
|
956
1363
|
|
957
1364
|
/*
|
958
|
-
* call-seq:
|
959
|
-
*
|
1365
|
+
* :call-seq:
|
1366
|
+
* namespace() → Namespace
|
960
1367
|
*
|
961
|
-
*
|
962
|
-
*/
|
963
|
-
static VALUE attr(VALUE self, VALUE name)
|
964
|
-
{
|
965
|
-
xmlNodePtr node;
|
966
|
-
xmlAttrPtr prop;
|
967
|
-
Data_Get_Struct(self, xmlNode, node);
|
968
|
-
prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
|
969
|
-
|
970
|
-
if(! prop) { return Qnil; }
|
971
|
-
return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
|
972
|
-
}
|
973
|
-
|
974
|
-
/*
|
975
|
-
* call-seq:
|
976
|
-
* attribute_with_ns(name, namespace)
|
1368
|
+
* [Returns] The Namespace of the element or attribute node, or +nil+ if there is no namespace.
|
977
1369
|
*
|
978
|
-
*
|
979
|
-
*/
|
980
|
-
static VALUE attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
|
981
|
-
{
|
982
|
-
xmlNodePtr node;
|
983
|
-
xmlAttrPtr prop;
|
984
|
-
Data_Get_Struct(self, xmlNode, node);
|
985
|
-
prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
|
986
|
-
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
|
987
|
-
|
988
|
-
if(! prop) { return Qnil; }
|
989
|
-
return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
|
990
|
-
}
|
991
|
-
|
992
|
-
/*
|
993
|
-
* call-seq:
|
994
|
-
* attribute_nodes()
|
1370
|
+
* *Example:*
|
995
1371
|
*
|
996
|
-
*
|
1372
|
+
* doc = Nokogiri::XML(<<~EOF)
|
1373
|
+
* <root>
|
1374
|
+
* <first/>
|
1375
|
+
* <second xmlns="http://example.com/child"/>
|
1376
|
+
* <foo:third xmlns:foo="http://example.com/foo"/>
|
1377
|
+
* </root>
|
1378
|
+
* EOF
|
1379
|
+
* doc.at_xpath("//first").namespace
|
1380
|
+
* # => nil
|
1381
|
+
* doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace
|
1382
|
+
* # => #(Namespace:0x3c { href = "http://example.com/child" })
|
1383
|
+
* doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace
|
1384
|
+
* # => #(Namespace:0x50 { prefix = "foo", href = "http://example.com/foo" })
|
997
1385
|
*/
|
998
|
-
static VALUE
|
1386
|
+
static VALUE
|
1387
|
+
rb_xml_node_namespace(VALUE rb_node)
|
999
1388
|
{
|
1000
|
-
|
1001
|
-
|
1002
|
-
VALUE attr;
|
1003
|
-
|
1004
|
-
Data_Get_Struct(self, xmlNode, node);
|
1389
|
+
xmlNodePtr c_node ;
|
1390
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1005
1391
|
|
1006
|
-
|
1007
|
-
|
1392
|
+
if (c_node->ns) {
|
1393
|
+
return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
|
1394
|
+
}
|
1008
1395
|
|
1009
|
-
return
|
1396
|
+
return Qnil ;
|
1010
1397
|
}
|
1011
1398
|
|
1012
|
-
|
1013
1399
|
/*
|
1014
|
-
*
|
1015
|
-
*
|
1400
|
+
* :call-seq:
|
1401
|
+
* namespace_definitions() → Array<Nokogiri::XML::Namespace>
|
1016
1402
|
*
|
1017
|
-
*
|
1018
|
-
*
|
1019
|
-
|
1020
|
-
static VALUE namespace(VALUE self)
|
1021
|
-
{
|
1022
|
-
xmlNodePtr node ;
|
1023
|
-
Data_Get_Struct(self, xmlNode, node);
|
1024
|
-
|
1025
|
-
if (node->ns) {
|
1026
|
-
return Nokogiri_wrap_xml_namespace(node->doc, node->ns);
|
1027
|
-
}
|
1028
|
-
|
1029
|
-
return Qnil ;
|
1030
|
-
}
|
1031
|
-
|
1032
|
-
/*
|
1033
|
-
* call-seq:
|
1034
|
-
* namespace_definitions()
|
1403
|
+
* [Returns]
|
1404
|
+
* Namespaces that are defined directly on this node, as an Array of Namespace objects. The array
|
1405
|
+
* will be empty if no namespaces are defined on this node.
|
1035
1406
|
*
|
1036
|
-
*
|
1407
|
+
* *Example:*
|
1408
|
+
*
|
1409
|
+
* doc = Nokogiri::XML(<<~EOF)
|
1410
|
+
* <root xmlns="http://example.com/root">
|
1411
|
+
* <first/>
|
1412
|
+
* <second xmlns="http://example.com/child" xmlns:unused="http://example.com/unused"/>
|
1413
|
+
* <foo:third xmlns:foo="http://example.com/foo"/>
|
1414
|
+
* </root>
|
1415
|
+
* EOF
|
1416
|
+
* doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_definitions
|
1417
|
+
* # => []
|
1418
|
+
* doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace_definitions
|
1419
|
+
* # => [#(Namespace:0x3c { href = "http://example.com/child" }),
|
1420
|
+
* # #(Namespace:0x50 {
|
1421
|
+
* # prefix = "unused",
|
1422
|
+
* # href = "http://example.com/unused"
|
1423
|
+
* # })]
|
1424
|
+
* doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace_definitions
|
1425
|
+
* # => [#(Namespace:0x64 { prefix = "foo", href = "http://example.com/foo" })]
|
1037
1426
|
*/
|
1038
|
-
static VALUE
|
1427
|
+
static VALUE
|
1428
|
+
namespace_definitions(VALUE rb_node)
|
1039
1429
|
{
|
1040
1430
|
/* this code in the mode of xmlHasProp() */
|
1041
|
-
xmlNodePtr
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
Data_Get_Struct(self, xmlNode, node);
|
1431
|
+
xmlNodePtr c_node ;
|
1432
|
+
xmlNsPtr c_namespace;
|
1433
|
+
VALUE definitions = rb_ary_new();
|
1046
1434
|
|
1047
|
-
|
1435
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1048
1436
|
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1437
|
+
c_namespace = c_node->nsDef;
|
1438
|
+
if (!c_namespace) {
|
1439
|
+
return definitions;
|
1440
|
+
}
|
1052
1441
|
|
1053
|
-
while(
|
1054
|
-
rb_ary_push(
|
1055
|
-
|
1442
|
+
while (c_namespace != NULL) {
|
1443
|
+
rb_ary_push(definitions, noko_xml_namespace_wrap(c_namespace, c_node->doc));
|
1444
|
+
c_namespace = c_namespace->next;
|
1056
1445
|
}
|
1057
1446
|
|
1058
|
-
return
|
1447
|
+
return definitions;
|
1059
1448
|
}
|
1060
1449
|
|
1061
1450
|
/*
|
1062
|
-
*
|
1063
|
-
*
|
1451
|
+
* :call-seq:
|
1452
|
+
* namespace_scopes() → Array<Nokogiri::XML::Namespace>
|
1453
|
+
*
|
1454
|
+
* [Returns] Array of all the Namespaces on this node and its ancestors.
|
1064
1455
|
*
|
1065
|
-
*
|
1066
|
-
*
|
1067
|
-
*
|
1068
|
-
*
|
1456
|
+
* See also #namespaces
|
1457
|
+
*
|
1458
|
+
* *Example:*
|
1459
|
+
*
|
1460
|
+
* doc = Nokogiri::XML(<<~EOF)
|
1461
|
+
* <root xmlns="http://example.com/root" xmlns:bar="http://example.com/bar">
|
1462
|
+
* <first/>
|
1463
|
+
* <second xmlns="http://example.com/child"/>
|
1464
|
+
* <third xmlns:foo="http://example.com/foo"/>
|
1465
|
+
* </root>
|
1466
|
+
* EOF
|
1467
|
+
* doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_scopes
|
1468
|
+
* # => [#(Namespace:0x3c { href = "http://example.com/root" }),
|
1469
|
+
* # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
|
1470
|
+
* doc.at_xpath("//child:second", "child" => "http://example.com/child").namespace_scopes
|
1471
|
+
* # => [#(Namespace:0x64 { href = "http://example.com/child" }),
|
1472
|
+
* # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
|
1473
|
+
* doc.at_xpath("//root:third", "root" => "http://example.com/root").namespace_scopes
|
1474
|
+
* # => [#(Namespace:0x78 { prefix = "foo", href = "http://example.com/foo" }),
|
1475
|
+
* # #(Namespace:0x3c { href = "http://example.com/root" }),
|
1476
|
+
* # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
|
1069
1477
|
*/
|
1070
|
-
static VALUE
|
1478
|
+
static VALUE
|
1479
|
+
rb_xml_node_namespace_scopes(VALUE rb_node)
|
1071
1480
|
{
|
1072
|
-
xmlNodePtr
|
1073
|
-
|
1074
|
-
|
1481
|
+
xmlNodePtr c_node ;
|
1482
|
+
xmlNsPtr *namespaces;
|
1483
|
+
VALUE scopes = rb_ary_new();
|
1075
1484
|
int j;
|
1076
1485
|
|
1077
|
-
|
1486
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1078
1487
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1488
|
+
namespaces = xmlGetNsList(c_node->doc, c_node);
|
1489
|
+
if (!namespaces) {
|
1490
|
+
return scopes;
|
1491
|
+
}
|
1083
1492
|
|
1084
|
-
for (j = 0 ;
|
1085
|
-
rb_ary_push(
|
1493
|
+
for (j = 0 ; namespaces[j] != NULL ; ++j) {
|
1494
|
+
rb_ary_push(scopes, noko_xml_namespace_wrap(namespaces[j], c_node->doc));
|
1086
1495
|
}
|
1087
1496
|
|
1088
|
-
xmlFree(
|
1089
|
-
return
|
1497
|
+
xmlFree(namespaces);
|
1498
|
+
return scopes;
|
1090
1499
|
}
|
1091
1500
|
|
1092
1501
|
/*
|
@@ -1095,10 +1504,11 @@ static VALUE namespace_scopes(VALUE self)
|
|
1095
1504
|
*
|
1096
1505
|
* Get the type for this Node
|
1097
1506
|
*/
|
1098
|
-
static VALUE
|
1507
|
+
static VALUE
|
1508
|
+
node_type(VALUE self)
|
1099
1509
|
{
|
1100
1510
|
xmlNodePtr node;
|
1101
|
-
|
1511
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1102
1512
|
return INT2NUM((long)node->type);
|
1103
1513
|
}
|
1104
1514
|
|
@@ -1108,16 +1518,17 @@ static VALUE node_type(VALUE self)
|
|
1108
1518
|
*
|
1109
1519
|
* Set the content for this Node
|
1110
1520
|
*/
|
1111
|
-
static VALUE
|
1521
|
+
static VALUE
|
1522
|
+
set_native_content(VALUE self, VALUE content)
|
1112
1523
|
{
|
1113
1524
|
xmlNodePtr node, child, next ;
|
1114
|
-
|
1525
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1115
1526
|
|
1116
1527
|
child = node->children;
|
1117
1528
|
while (NULL != child) {
|
1118
1529
|
next = child->next ;
|
1119
1530
|
xmlUnlinkNode(child) ;
|
1120
|
-
|
1531
|
+
noko_xml_document_pin_node(child);
|
1121
1532
|
child = next ;
|
1122
1533
|
}
|
1123
1534
|
|
@@ -1125,42 +1536,20 @@ static VALUE set_native_content(VALUE self, VALUE content)
|
|
1125
1536
|
return content;
|
1126
1537
|
}
|
1127
1538
|
|
1128
|
-
/*
|
1129
|
-
* call-seq:
|
1130
|
-
* content
|
1131
|
-
*
|
1132
|
-
* Returns the plaintext content for this Node. Note that entities will always
|
1133
|
-
* be expanded in the returned string.
|
1134
|
-
*/
|
1135
|
-
static VALUE get_native_content(VALUE self)
|
1136
|
-
{
|
1137
|
-
xmlNodePtr node;
|
1138
|
-
xmlChar * content;
|
1139
|
-
|
1140
|
-
Data_Get_Struct(self, xmlNode, node);
|
1141
|
-
|
1142
|
-
content = xmlNodeGetContent(node);
|
1143
|
-
if(content) {
|
1144
|
-
VALUE rval = NOKOGIRI_STR_NEW2(content);
|
1145
|
-
xmlFree(content);
|
1146
|
-
return rval;
|
1147
|
-
}
|
1148
|
-
return Qnil;
|
1149
|
-
}
|
1150
|
-
|
1151
1539
|
/*
|
1152
1540
|
* call-seq:
|
1153
1541
|
* lang=
|
1154
1542
|
*
|
1155
1543
|
* Set the language of a node, i.e. the values of the xml:lang attribute.
|
1156
1544
|
*/
|
1157
|
-
static VALUE
|
1545
|
+
static VALUE
|
1546
|
+
set_lang(VALUE self_rb, VALUE lang_rb)
|
1158
1547
|
{
|
1159
1548
|
xmlNodePtr self ;
|
1160
|
-
xmlChar*
|
1549
|
+
xmlChar *lang ;
|
1161
1550
|
|
1162
|
-
|
1163
|
-
lang = (xmlChar*)StringValueCStr(lang_rb);
|
1551
|
+
Noko_Node_Get_Struct(self_rb, xmlNode, self);
|
1552
|
+
lang = (xmlChar *)StringValueCStr(lang_rb);
|
1164
1553
|
|
1165
1554
|
xmlNodeSetLang(self, lang);
|
1166
1555
|
|
@@ -1174,13 +1563,14 @@ static VALUE set_lang(VALUE self_rb, VALUE lang_rb)
|
|
1174
1563
|
* Searches the language of a node, i.e. the values of the xml:lang attribute or
|
1175
1564
|
* the one carried by the nearest ancestor.
|
1176
1565
|
*/
|
1177
|
-
static VALUE
|
1566
|
+
static VALUE
|
1567
|
+
get_lang(VALUE self_rb)
|
1178
1568
|
{
|
1179
1569
|
xmlNodePtr self ;
|
1180
|
-
xmlChar*
|
1570
|
+
xmlChar *lang ;
|
1181
1571
|
VALUE lang_rb ;
|
1182
1572
|
|
1183
|
-
|
1573
|
+
Noko_Node_Get_Struct(self_rb, xmlNode, self);
|
1184
1574
|
|
1185
1575
|
lang = xmlNodeGetLang(self);
|
1186
1576
|
if (lang) {
|
@@ -1193,7 +1583,8 @@ static VALUE get_lang(VALUE self_rb)
|
|
1193
1583
|
}
|
1194
1584
|
|
1195
1585
|
/* :nodoc: */
|
1196
|
-
static VALUE
|
1586
|
+
static VALUE
|
1587
|
+
add_child(VALUE self, VALUE new_child)
|
1197
1588
|
{
|
1198
1589
|
return reparent_node_with(self, new_child, xmlAddChild);
|
1199
1590
|
}
|
@@ -1204,15 +1595,16 @@ static VALUE add_child(VALUE self, VALUE new_child)
|
|
1204
1595
|
*
|
1205
1596
|
* Get the parent Node for this Node
|
1206
1597
|
*/
|
1207
|
-
static VALUE
|
1598
|
+
static VALUE
|
1599
|
+
get_parent(VALUE self)
|
1208
1600
|
{
|
1209
1601
|
xmlNodePtr node, parent;
|
1210
|
-
|
1602
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1211
1603
|
|
1212
1604
|
parent = node->parent;
|
1213
|
-
if(!parent) { return Qnil; }
|
1605
|
+
if (!parent) { return Qnil; }
|
1214
1606
|
|
1215
|
-
return
|
1607
|
+
return noko_xml_node_wrap(Qnil, parent) ;
|
1216
1608
|
}
|
1217
1609
|
|
1218
1610
|
/*
|
@@ -1221,11 +1613,12 @@ static VALUE get_parent(VALUE self)
|
|
1221
1613
|
*
|
1222
1614
|
* Set the name for this Node
|
1223
1615
|
*/
|
1224
|
-
static VALUE
|
1616
|
+
static VALUE
|
1617
|
+
set_name(VALUE self, VALUE new_name)
|
1225
1618
|
{
|
1226
1619
|
xmlNodePtr node;
|
1227
|
-
|
1228
|
-
xmlNodeSetName(node, (xmlChar*)StringValueCStr(new_name));
|
1620
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1621
|
+
xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
|
1229
1622
|
return new_name;
|
1230
1623
|
}
|
1231
1624
|
|
@@ -1235,11 +1628,12 @@ static VALUE set_name(VALUE self, VALUE new_name)
|
|
1235
1628
|
*
|
1236
1629
|
* Returns the name for this Node
|
1237
1630
|
*/
|
1238
|
-
static VALUE
|
1631
|
+
static VALUE
|
1632
|
+
get_name(VALUE self)
|
1239
1633
|
{
|
1240
1634
|
xmlNodePtr node;
|
1241
|
-
|
1242
|
-
if(node->name) {
|
1635
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1636
|
+
if (node->name) {
|
1243
1637
|
return NOKOGIRI_STR_NEW2(node->name);
|
1244
1638
|
}
|
1245
1639
|
return Qnil;
|
@@ -1251,28 +1645,39 @@ static VALUE get_name(VALUE self)
|
|
1251
1645
|
*
|
1252
1646
|
* Returns the path associated with this Node
|
1253
1647
|
*/
|
1254
|
-
static VALUE
|
1648
|
+
static VALUE
|
1649
|
+
rb_xml_node_path(VALUE rb_node)
|
1255
1650
|
{
|
1256
|
-
xmlNodePtr
|
1257
|
-
xmlChar *
|
1651
|
+
xmlNodePtr c_node;
|
1652
|
+
xmlChar *c_path ;
|
1258
1653
|
VALUE rval;
|
1259
1654
|
|
1260
|
-
|
1655
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1656
|
+
|
1657
|
+
c_path = xmlGetNodePath(c_node);
|
1658
|
+
if (c_path == NULL) {
|
1659
|
+
// see https://github.com/sparklemotion/nokogiri/issues/2250
|
1660
|
+
// this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
|
1661
|
+
// do this for now to preserve the behavior across libxml2 versions.
|
1662
|
+
rval = NOKOGIRI_STR_NEW2("?");
|
1663
|
+
} else {
|
1664
|
+
rval = NOKOGIRI_STR_NEW2(c_path);
|
1665
|
+
xmlFree(c_path);
|
1666
|
+
}
|
1261
1667
|
|
1262
|
-
path = xmlGetNodePath(node);
|
1263
|
-
rval = NOKOGIRI_STR_NEW2(path);
|
1264
|
-
xmlFree(path);
|
1265
1668
|
return rval ;
|
1266
1669
|
}
|
1267
1670
|
|
1268
1671
|
/* :nodoc: */
|
1269
|
-
static VALUE
|
1672
|
+
static VALUE
|
1673
|
+
add_next_sibling(VALUE self, VALUE new_sibling)
|
1270
1674
|
{
|
1271
1675
|
return reparent_node_with(self, new_sibling, xmlAddNextSibling) ;
|
1272
1676
|
}
|
1273
1677
|
|
1274
1678
|
/* :nodoc: */
|
1275
|
-
static VALUE
|
1679
|
+
static VALUE
|
1680
|
+
add_previous_sibling(VALUE self, VALUE new_sibling)
|
1276
1681
|
{
|
1277
1682
|
return reparent_node_with(self, new_sibling, xmlAddPrevSibling) ;
|
1278
1683
|
}
|
@@ -1283,7 +1688,8 @@ static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
|
|
1283
1688
|
*
|
1284
1689
|
* Write this Node to +io+ with +encoding+ and +options+
|
1285
1690
|
*/
|
1286
|
-
static VALUE
|
1691
|
+
static VALUE
|
1692
|
+
native_write_to(
|
1287
1693
|
VALUE self,
|
1288
1694
|
VALUE io,
|
1289
1695
|
VALUE encoding,
|
@@ -1292,10 +1698,10 @@ static VALUE native_write_to(
|
|
1292
1698
|
)
|
1293
1699
|
{
|
1294
1700
|
xmlNodePtr node;
|
1295
|
-
const char *
|
1701
|
+
const char *before_indent;
|
1296
1702
|
xmlSaveCtxtPtr savectx;
|
1297
1703
|
|
1298
|
-
|
1704
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1299
1705
|
|
1300
1706
|
xmlIndentTreeOutput = 1;
|
1301
1707
|
|
@@ -1304,8 +1710,8 @@ static VALUE native_write_to(
|
|
1304
1710
|
xmlTreeIndentString = StringValueCStr(indent_string);
|
1305
1711
|
|
1306
1712
|
savectx = xmlSaveToIO(
|
1307
|
-
(xmlOutputWriteCallback)
|
1308
|
-
(xmlOutputCloseCallback)
|
1713
|
+
(xmlOutputWriteCallback)noko_io_write,
|
1714
|
+
(xmlOutputCloseCallback)noko_io_close,
|
1309
1715
|
(void *)io,
|
1310
1716
|
RTEST(encoding) ? StringValueCStr(encoding) : NULL,
|
1311
1717
|
(int)NUM2INT(options)
|
@@ -1319,92 +1725,102 @@ static VALUE native_write_to(
|
|
1319
1725
|
}
|
1320
1726
|
|
1321
1727
|
/*
|
1322
|
-
* call-seq:
|
1323
|
-
*
|
1728
|
+
* :call-seq:
|
1729
|
+
* line() → Integer
|
1324
1730
|
*
|
1325
|
-
* Returns
|
1731
|
+
* [Returns] The line number of this Node.
|
1732
|
+
*
|
1733
|
+
* ---
|
1734
|
+
*
|
1735
|
+
* <b> ⚠ The CRuby and JRuby implementations differ in important ways! </b>
|
1736
|
+
*
|
1737
|
+
* Semantic differences:
|
1738
|
+
* - The CRuby method reflects the node's line number <i>in the parsed string</i>
|
1739
|
+
* - The JRuby method reflects the node's line number <i>in the final DOM structure</i> after
|
1740
|
+
* corrections have been applied
|
1741
|
+
*
|
1742
|
+
* Performance differences:
|
1743
|
+
* - The CRuby method is {O(1)}[https://en.wikipedia.org/wiki/Time_complexity#Constant_time]
|
1744
|
+
* (constant time)
|
1745
|
+
* - The JRuby method is {O(n)}[https://en.wikipedia.org/wiki/Time_complexity#Linear_time] (linear
|
1746
|
+
* time, where n is the number of nodes before/above the element in the DOM)
|
1747
|
+
*
|
1748
|
+
* If you'd like to help improve the JRuby implementation, please review these issues and reach out
|
1749
|
+
* to the maintainers:
|
1750
|
+
* - https://github.com/sparklemotion/nokogiri/issues/1223
|
1751
|
+
* - https://github.com/sparklemotion/nokogiri/pull/2177
|
1752
|
+
* - https://github.com/sparklemotion/nokogiri/issues/2380
|
1326
1753
|
*/
|
1327
|
-
static VALUE
|
1754
|
+
static VALUE
|
1755
|
+
rb_xml_node_line(VALUE rb_node)
|
1328
1756
|
{
|
1329
|
-
xmlNodePtr
|
1330
|
-
|
1757
|
+
xmlNodePtr c_node;
|
1758
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1331
1759
|
|
1332
|
-
return INT2NUM(xmlGetLineNo(
|
1760
|
+
return INT2NUM(xmlGetLineNo(c_node));
|
1333
1761
|
}
|
1334
1762
|
|
1335
1763
|
/*
|
1336
1764
|
* call-seq:
|
1337
|
-
*
|
1338
|
-
*
|
1339
|
-
*
|
1340
|
-
* as if parsed XML for this node had included an attribute
|
1341
|
-
* 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
|
1342
|
-
* added by passing 'nil' for prefix. Namespaces added this way will not
|
1343
|
-
* show up in #attributes, but they will be included as an xmlns attribute
|
1344
|
-
* when the node is serialized to XML.
|
1765
|
+
* line=(num)
|
1766
|
+
*
|
1767
|
+
* Sets the line for this Node. num must be less than 65535.
|
1345
1768
|
*/
|
1346
|
-
static VALUE
|
1769
|
+
static VALUE
|
1770
|
+
rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
|
1347
1771
|
{
|
1348
|
-
xmlNodePtr
|
1349
|
-
|
1772
|
+
xmlNodePtr c_node;
|
1773
|
+
int line_number = NUM2INT(rb_line_number);
|
1350
1774
|
|
1351
|
-
|
1352
|
-
namespace = node ;
|
1775
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1353
1776
|
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
namespace = node->parent;
|
1777
|
+
// libxml2 optionally uses xmlNode.psvi to store longer line numbers, but only for text nodes.
|
1778
|
+
// search for "psvi" in SAX2.c and tree.c to learn more.
|
1779
|
+
if (line_number < 65535) {
|
1780
|
+
c_node->line = (short) line_number;
|
1781
|
+
} else {
|
1782
|
+
c_node->line = 65535;
|
1783
|
+
if (c_node->type == XML_TEXT_NODE) {
|
1784
|
+
c_node->psvi = (void *)(ptrdiff_t) line_number;
|
1363
1785
|
}
|
1364
|
-
ns = xmlNewNs(
|
1365
|
-
namespace,
|
1366
|
-
(const xmlChar *)StringValueCStr(href),
|
1367
|
-
(const xmlChar *)(NIL_P(prefix) ? NULL : StringValueCStr(prefix))
|
1368
|
-
);
|
1369
1786
|
}
|
1370
1787
|
|
1371
|
-
|
1372
|
-
|
1373
|
-
if(NIL_P(prefix) || node != namespace) { xmlSetNs(node, ns); }
|
1374
|
-
|
1375
|
-
return Nokogiri_wrap_xml_namespace(node->doc, ns);
|
1788
|
+
return rb_line_number;
|
1376
1789
|
}
|
1377
1790
|
|
1378
|
-
/*
|
1379
|
-
|
1380
|
-
*
|
1381
|
-
*
|
1382
|
-
* Create a new node with +name+ sharing GC lifecycle with +document+
|
1383
|
-
*/
|
1384
|
-
static VALUE new(int argc, VALUE *argv, VALUE klass)
|
1791
|
+
/* :nodoc: documented in lib/nokogiri/xml/node.rb */
|
1792
|
+
static VALUE
|
1793
|
+
rb_xml_node_new(int argc, VALUE *argv, VALUE klass)
|
1385
1794
|
{
|
1386
|
-
|
1387
|
-
xmlNodePtr
|
1388
|
-
VALUE
|
1389
|
-
VALUE
|
1795
|
+
xmlNodePtr c_document_node;
|
1796
|
+
xmlNodePtr c_node;
|
1797
|
+
VALUE rb_name;
|
1798
|
+
VALUE rb_document_node;
|
1390
1799
|
VALUE rest;
|
1391
1800
|
VALUE rb_node;
|
1392
1801
|
|
1393
|
-
rb_scan_args(argc, argv, "2*", &
|
1802
|
+
rb_scan_args(argc, argv, "2*", &rb_name, &rb_document_node, &rest);
|
1394
1803
|
|
1395
|
-
|
1804
|
+
if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlNode)) {
|
1805
|
+
rb_raise(rb_eArgError, "document must be a Nokogiri::XML::Node");
|
1806
|
+
}
|
1807
|
+
if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlDocument)) {
|
1808
|
+
// TODO: deprecate allowing Node
|
1809
|
+
NOKO_WARN_DEPRECATION("Passing a Node as the second parameter to Node.new is deprecated. Please pass a Document instead, or prefer an alternative constructor like Node#add_child. This will become an error in a future release of Nokogiri.");
|
1810
|
+
}
|
1811
|
+
Noko_Node_Get_Struct(rb_document_node, xmlNode, c_document_node);
|
1396
1812
|
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1813
|
+
c_node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(rb_name));
|
1814
|
+
c_node->doc = c_document_node->doc;
|
1815
|
+
noko_xml_document_pin_node(c_node);
|
1400
1816
|
|
1401
|
-
rb_node =
|
1817
|
+
rb_node = noko_xml_node_wrap(
|
1402
1818
|
klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
|
1403
|
-
|
1819
|
+
c_node
|
1404
1820
|
);
|
1405
1821
|
rb_obj_call_init(rb_node, argc, argv);
|
1406
1822
|
|
1407
|
-
if(rb_block_given_p()) { rb_yield(rb_node); }
|
1823
|
+
if (rb_block_given_p()) { rb_yield(rb_node); }
|
1408
1824
|
|
1409
1825
|
return rb_node;
|
1410
1826
|
}
|
@@ -1415,13 +1831,14 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
|
|
1415
1831
|
*
|
1416
1832
|
* Returns the Node as html.
|
1417
1833
|
*/
|
1418
|
-
static VALUE
|
1834
|
+
static VALUE
|
1835
|
+
dump_html(VALUE self)
|
1419
1836
|
{
|
1420
1837
|
xmlBufferPtr buf ;
|
1421
1838
|
xmlNodePtr node ;
|
1422
1839
|
VALUE html;
|
1423
1840
|
|
1424
|
-
|
1841
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1425
1842
|
|
1426
1843
|
buf = xmlBufferCreate() ;
|
1427
1844
|
htmlNodeDump(buf, node->doc, node);
|
@@ -1436,11 +1853,12 @@ static VALUE dump_html(VALUE self)
|
|
1436
1853
|
*
|
1437
1854
|
* Compare this Node to +other+ with respect to their Document
|
1438
1855
|
*/
|
1439
|
-
static VALUE
|
1856
|
+
static VALUE
|
1857
|
+
compare(VALUE self, VALUE _other)
|
1440
1858
|
{
|
1441
1859
|
xmlNodePtr node, other;
|
1442
|
-
|
1443
|
-
|
1860
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1861
|
+
Noko_Node_Get_Struct(_other, xmlNode, other);
|
1444
1862
|
|
1445
1863
|
return INT2NUM((long)xmlXPathCmpNodes(other, node));
|
1446
1864
|
}
|
@@ -1453,13 +1871,14 @@ static VALUE compare(VALUE self, VALUE _other)
|
|
1453
1871
|
* Loads and substitutes all xinclude elements below the node. The
|
1454
1872
|
* parser context will be initialized with +options+.
|
1455
1873
|
*/
|
1456
|
-
static VALUE
|
1874
|
+
static VALUE
|
1875
|
+
process_xincludes(VALUE self, VALUE options)
|
1457
1876
|
{
|
1458
1877
|
int rcode ;
|
1459
1878
|
xmlNodePtr node;
|
1460
1879
|
VALUE error_list = rb_ary_new();
|
1461
1880
|
|
1462
|
-
|
1881
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1463
1882
|
|
1464
1883
|
xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
|
1465
1884
|
rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
|
@@ -1469,7 +1888,7 @@ static VALUE process_xincludes(VALUE self, VALUE options)
|
|
1469
1888
|
xmlErrorPtr error;
|
1470
1889
|
|
1471
1890
|
error = xmlGetLastError();
|
1472
|
-
if(error) {
|
1891
|
+
if (error) {
|
1473
1892
|
rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
|
1474
1893
|
} else {
|
1475
1894
|
rb_raise(rb_eRuntimeError, "Could not perform xinclude substitution");
|
@@ -1481,7 +1900,8 @@ static VALUE process_xincludes(VALUE self, VALUE options)
|
|
1481
1900
|
|
1482
1901
|
|
1483
1902
|
/* TODO: DOCUMENT ME */
|
1484
|
-
static VALUE
|
1903
|
+
static VALUE
|
1904
|
+
in_context(VALUE self, VALUE _str, VALUE _options)
|
1485
1905
|
{
|
1486
1906
|
xmlNodePtr node, list = 0, tmp, child_iter, node_children, doc_children;
|
1487
1907
|
xmlNodeSetPtr set;
|
@@ -1489,7 +1909,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1489
1909
|
VALUE doc, err;
|
1490
1910
|
int doc_is_empty;
|
1491
1911
|
|
1492
|
-
|
1912
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1493
1913
|
|
1494
1914
|
doc = DOC_RUBY_OBJECT(node->doc);
|
1495
1915
|
err = rb_iv_get(doc, "@errors");
|
@@ -1530,9 +1950,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1530
1950
|
*/
|
1531
1951
|
child_iter = node->doc->children ;
|
1532
1952
|
while (child_iter) {
|
1533
|
-
|
1534
|
-
child_iter->parent = (xmlNodePtr)node->doc;
|
1535
|
-
}
|
1953
|
+
child_iter->parent = (xmlNodePtr)node->doc;
|
1536
1954
|
child_iter = child_iter->next;
|
1537
1955
|
}
|
1538
1956
|
|
@@ -1562,12 +1980,12 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1562
1980
|
|
1563
1981
|
/* FIXME: This probably needs to handle more constants... */
|
1564
1982
|
switch (error) {
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1983
|
+
case XML_ERR_INTERNAL_ERROR:
|
1984
|
+
case XML_ERR_NO_MEMORY:
|
1985
|
+
rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
|
1986
|
+
break;
|
1987
|
+
default:
|
1988
|
+
break;
|
1571
1989
|
}
|
1572
1990
|
|
1573
1991
|
set = xmlXPathNodeSetCreate(NULL);
|
@@ -1576,178 +1994,172 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1576
1994
|
tmp = list->next;
|
1577
1995
|
list->next = NULL;
|
1578
1996
|
xmlXPathNodeSetAddUnique(set, list);
|
1579
|
-
|
1997
|
+
noko_xml_document_pin_node(list);
|
1580
1998
|
list = tmp;
|
1581
1999
|
}
|
1582
2000
|
|
1583
|
-
return
|
2001
|
+
return noko_xml_node_set_wrap(set, doc);
|
1584
2002
|
}
|
1585
2003
|
|
1586
|
-
|
1587
|
-
|
2004
|
+
VALUE
|
2005
|
+
noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
|
1588
2006
|
{
|
1589
|
-
VALUE
|
1590
|
-
VALUE node_cache = Qnil ;
|
1591
|
-
VALUE rb_node = Qnil ;
|
2007
|
+
VALUE rb_document, rb_node_cache, rb_node;
|
1592
2008
|
nokogiriTuplePtr node_has_a_document;
|
1593
|
-
xmlDocPtr
|
1594
|
-
void (*mark_method)(xmlNodePtr) = NULL ;
|
2009
|
+
xmlDocPtr c_doc;
|
1595
2010
|
|
1596
|
-
assert(
|
2011
|
+
assert(c_node);
|
1597
2012
|
|
1598
|
-
if(
|
1599
|
-
return DOC_RUBY_OBJECT(
|
2013
|
+
if (c_node->type == XML_DOCUMENT_NODE || c_node->type == XML_HTML_DOCUMENT_NODE) {
|
2014
|
+
return DOC_RUBY_OBJECT(c_node->doc);
|
1600
2015
|
}
|
1601
2016
|
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
if (doc->type == XML_DOCUMENT_FRAG_NODE) { doc = doc->doc; }
|
1607
|
-
node_has_a_document = DOC_RUBY_OBJECT_TEST(doc);
|
2017
|
+
c_doc = c_node->doc;
|
2018
|
+
|
2019
|
+
// Nodes yielded from XML::Reader don't have a fully-realized Document
|
2020
|
+
node_has_a_document = DOC_RUBY_OBJECT_TEST(c_doc);
|
1608
2021
|
|
1609
|
-
if(
|
1610
|
-
return (VALUE)
|
2022
|
+
if (c_node->_private && node_has_a_document) {
|
2023
|
+
return (VALUE)c_node->_private;
|
1611
2024
|
}
|
1612
2025
|
|
1613
|
-
if(!RTEST(
|
1614
|
-
switch(
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
2026
|
+
if (!RTEST(rb_class)) {
|
2027
|
+
switch (c_node->type) {
|
2028
|
+
case XML_ELEMENT_NODE:
|
2029
|
+
rb_class = cNokogiriXmlElement;
|
2030
|
+
break;
|
2031
|
+
case XML_TEXT_NODE:
|
2032
|
+
rb_class = cNokogiriXmlText;
|
2033
|
+
break;
|
2034
|
+
case XML_ATTRIBUTE_NODE:
|
2035
|
+
rb_class = cNokogiriXmlAttr;
|
2036
|
+
break;
|
2037
|
+
case XML_ENTITY_REF_NODE:
|
2038
|
+
rb_class = cNokogiriXmlEntityReference;
|
2039
|
+
break;
|
2040
|
+
case XML_COMMENT_NODE:
|
2041
|
+
rb_class = cNokogiriXmlComment;
|
2042
|
+
break;
|
2043
|
+
case XML_DOCUMENT_FRAG_NODE:
|
2044
|
+
rb_class = cNokogiriXmlDocumentFragment;
|
2045
|
+
break;
|
2046
|
+
case XML_PI_NODE:
|
2047
|
+
rb_class = cNokogiriXmlProcessingInstruction;
|
2048
|
+
break;
|
2049
|
+
case XML_ENTITY_DECL:
|
2050
|
+
rb_class = cNokogiriXmlEntityDecl;
|
2051
|
+
break;
|
2052
|
+
case XML_CDATA_SECTION_NODE:
|
2053
|
+
rb_class = cNokogiriXmlCData;
|
2054
|
+
break;
|
2055
|
+
case XML_DTD_NODE:
|
2056
|
+
rb_class = cNokogiriXmlDtd;
|
2057
|
+
break;
|
2058
|
+
case XML_ATTRIBUTE_DECL:
|
2059
|
+
rb_class = cNokogiriXmlAttributeDecl;
|
2060
|
+
break;
|
2061
|
+
case XML_ELEMENT_DECL:
|
2062
|
+
rb_class = cNokogiriXmlElementDecl;
|
2063
|
+
break;
|
2064
|
+
default:
|
2065
|
+
rb_class = cNokogiriXmlNode;
|
1653
2066
|
}
|
1654
2067
|
}
|
1655
2068
|
|
1656
|
-
|
1657
|
-
|
1658
|
-
rb_node = Data_Wrap_Struct(klass, mark_method, debug_node_dealloc, node) ;
|
1659
|
-
node->_private = (void *)rb_node;
|
2069
|
+
rb_node = TypedData_Wrap_Struct(rb_class, &nokogiri_node_type, c_node) ;
|
2070
|
+
c_node->_private = (void *)rb_node;
|
1660
2071
|
|
1661
2072
|
if (node_has_a_document) {
|
1662
|
-
|
1663
|
-
|
1664
|
-
rb_ary_push(
|
1665
|
-
rb_funcall(
|
2073
|
+
rb_document = DOC_RUBY_OBJECT(c_doc);
|
2074
|
+
rb_node_cache = DOC_NODE_CACHE(c_doc);
|
2075
|
+
rb_ary_push(rb_node_cache, rb_node);
|
2076
|
+
rb_funcall(rb_document, id_decorate, 1, rb_node);
|
1666
2077
|
}
|
1667
2078
|
|
1668
2079
|
return rb_node ;
|
1669
2080
|
}
|
1670
2081
|
|
1671
2082
|
|
1672
|
-
|
2083
|
+
/*
|
2084
|
+
* return Array<Nokogiri::XML::Attr> containing the node's attributes
|
2085
|
+
*/
|
2086
|
+
VALUE
|
2087
|
+
noko_xml_node_attrs(xmlNodePtr c_node)
|
1673
2088
|
{
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
2089
|
+
VALUE rb_properties = rb_ary_new();
|
2090
|
+
xmlAttrPtr c_property;
|
2091
|
+
|
2092
|
+
c_property = c_node->properties ;
|
2093
|
+
while (c_property != NULL) {
|
2094
|
+
rb_ary_push(rb_properties, noko_xml_node_wrap(Qnil, (xmlNodePtr)c_property));
|
2095
|
+
c_property = c_property->next ;
|
1679
2096
|
}
|
1680
|
-
}
|
1681
2097
|
|
1682
|
-
|
1683
|
-
|
2098
|
+
return rb_properties;
|
2099
|
+
}
|
1684
2100
|
|
1685
|
-
void
|
2101
|
+
void
|
2102
|
+
noko_init_xml_node()
|
1686
2103
|
{
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
cNokogiriXmlNode
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
rb_define_method(
|
1698
|
-
rb_define_method(
|
1699
|
-
rb_define_method(
|
1700
|
-
rb_define_method(
|
1701
|
-
rb_define_method(
|
1702
|
-
rb_define_method(
|
1703
|
-
rb_define_method(
|
1704
|
-
rb_define_method(
|
1705
|
-
rb_define_method(
|
1706
|
-
rb_define_method(
|
1707
|
-
rb_define_method(
|
1708
|
-
rb_define_method(
|
1709
|
-
rb_define_method(
|
1710
|
-
rb_define_method(
|
1711
|
-
rb_define_method(
|
1712
|
-
rb_define_method(
|
1713
|
-
rb_define_method(
|
1714
|
-
rb_define_method(
|
1715
|
-
rb_define_method(
|
1716
|
-
rb_define_method(
|
1717
|
-
rb_define_method(
|
1718
|
-
rb_define_method(
|
1719
|
-
rb_define_method(
|
1720
|
-
rb_define_method(
|
1721
|
-
rb_define_method(
|
1722
|
-
rb_define_method(
|
1723
|
-
rb_define_method(
|
1724
|
-
rb_define_method(
|
1725
|
-
rb_define_method(
|
1726
|
-
rb_define_method(
|
1727
|
-
rb_define_method(
|
1728
|
-
rb_define_method(
|
1729
|
-
rb_define_method(
|
1730
|
-
rb_define_method(
|
1731
|
-
rb_define_method(
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
rb_define_private_method(
|
1737
|
-
rb_define_private_method(
|
1738
|
-
rb_define_private_method(
|
1739
|
-
rb_define_private_method(
|
1740
|
-
rb_define_private_method(
|
1741
|
-
rb_define_private_method(
|
1742
|
-
rb_define_private_method(
|
1743
|
-
rb_define_private_method(
|
1744
|
-
rb_define_private_method(
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
decorate = rb_intern("decorate");
|
1750
|
-
decorate_bang = rb_intern("decorate!");
|
2104
|
+
cNokogiriXmlNode = rb_define_class_under(mNokogiriXml, "Node", rb_cObject);
|
2105
|
+
|
2106
|
+
rb_undef_alloc_func(cNokogiriXmlNode);
|
2107
|
+
|
2108
|
+
rb_define_singleton_method(cNokogiriXmlNode, "new", rb_xml_node_new, -1);
|
2109
|
+
|
2110
|
+
rb_define_method(cNokogiriXmlNode, "add_namespace_definition", rb_xml_node_add_namespace_definition, 2);
|
2111
|
+
rb_define_method(cNokogiriXmlNode, "attribute", rb_xml_node_attribute, 1);
|
2112
|
+
rb_define_method(cNokogiriXmlNode, "attribute_nodes", rb_xml_node_attribute_nodes, 0);
|
2113
|
+
rb_define_method(cNokogiriXmlNode, "attribute_with_ns", rb_xml_node_attribute_with_ns, 2);
|
2114
|
+
rb_define_method(cNokogiriXmlNode, "blank?", rb_xml_node_blank_eh, 0);
|
2115
|
+
rb_define_method(cNokogiriXmlNode, "child", rb_xml_node_child, 0);
|
2116
|
+
rb_define_method(cNokogiriXmlNode, "children", rb_xml_node_children, 0);
|
2117
|
+
rb_define_method(cNokogiriXmlNode, "content", rb_xml_node_content, 0);
|
2118
|
+
rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
|
2119
|
+
rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
|
2120
|
+
rb_define_method(cNokogiriXmlNode, "document", rb_xml_node_document, 0);
|
2121
|
+
rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
|
2122
|
+
rb_define_method(cNokogiriXmlNode, "element_children", rb_xml_node_element_children, 0);
|
2123
|
+
rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
|
2124
|
+
rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
|
2125
|
+
rb_define_method(cNokogiriXmlNode, "first_element_child", rb_xml_node_first_element_child, 0);
|
2126
|
+
rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
|
2127
|
+
rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
|
2128
|
+
rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
|
2129
|
+
rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
|
2130
|
+
rb_define_method(cNokogiriXmlNode, "last_element_child", rb_xml_node_last_element_child, 0);
|
2131
|
+
rb_define_method(cNokogiriXmlNode, "line", rb_xml_node_line, 0);
|
2132
|
+
rb_define_method(cNokogiriXmlNode, "line=", rb_xml_node_line_set, 1);
|
2133
|
+
rb_define_method(cNokogiriXmlNode, "namespace", rb_xml_node_namespace, 0);
|
2134
|
+
rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
|
2135
|
+
rb_define_method(cNokogiriXmlNode, "namespace_scopes", rb_xml_node_namespace_scopes, 0);
|
2136
|
+
rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
|
2137
|
+
rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
|
2138
|
+
rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
|
2139
|
+
rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
|
2140
|
+
rb_define_method(cNokogiriXmlNode, "node_name", get_name, 0);
|
2141
|
+
rb_define_method(cNokogiriXmlNode, "node_name=", set_name, 1);
|
2142
|
+
rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
|
2143
|
+
rb_define_method(cNokogiriXmlNode, "parent", get_parent, 0);
|
2144
|
+
rb_define_method(cNokogiriXmlNode, "path", rb_xml_node_path, 0);
|
2145
|
+
rb_define_method(cNokogiriXmlNode, "pointer_id", rb_xml_node_pointer_id, 0);
|
2146
|
+
rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
|
2147
|
+
rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
|
2148
|
+
rb_define_method(cNokogiriXmlNode, "unlink", unlink_node, 0);
|
2149
|
+
|
2150
|
+
rb_define_private_method(cNokogiriXmlNode, "add_child_node", add_child, 1);
|
2151
|
+
rb_define_private_method(cNokogiriXmlNode, "add_next_sibling_node", add_next_sibling, 1);
|
2152
|
+
rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
|
2153
|
+
rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
|
2154
|
+
rb_define_private_method(cNokogiriXmlNode, "dump_html", dump_html, 0);
|
2155
|
+
rb_define_private_method(cNokogiriXmlNode, "get", get, 1);
|
2156
|
+
rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
|
2157
|
+
rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
|
2158
|
+
rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
|
2159
|
+
rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
|
2160
|
+
rb_define_private_method(cNokogiriXmlNode, "set", set, 2);
|
2161
|
+
rb_define_private_method(cNokogiriXmlNode, "set_namespace", set_namespace, 1);
|
2162
|
+
|
2163
|
+
id_decorate = rb_intern("decorate");
|
2164
|
+
id_decorate_bang = rb_intern("decorate!");
|
1751
2165
|
}
|
1752
|
-
|
1753
|
-
/* vim: set noet sw=4 sws=4 */
|