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