nokogiri 1.10.10 → 1.14.3-aarch64-linux
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 +44 -0
- data/LICENSE-DEPENDENCIES.md +1632 -1022
- data/LICENSE.md +1 -1
- data/README.md +185 -96
- data/bin/nokogiri +63 -50
- data/dependencies.yml +33 -66
- data/ext/nokogiri/depend +38 -358
- data/ext/nokogiri/extconf.rb +819 -421
- data/ext/nokogiri/gumbo.c +594 -0
- data/ext/nokogiri/html4_document.c +166 -0
- data/ext/nokogiri/html4_element_description.c +294 -0
- data/ext/nokogiri/html4_entity_lookup.c +37 -0
- data/ext/nokogiri/html4_sax_parser_context.c +114 -0
- data/ext/nokogiri/html4_sax_push_parser.c +95 -0
- data/ext/nokogiri/include/libexslt/exslt.h +108 -0
- data/ext/nokogiri/include/libexslt/exsltconfig.h +70 -0
- data/ext/nokogiri/include/libexslt/exsltexports.h +63 -0
- data/ext/nokogiri/include/libxml2/libxml/HTMLparser.h +306 -0
- data/ext/nokogiri/include/libxml2/libxml/HTMLtree.h +147 -0
- data/ext/nokogiri/include/libxml2/libxml/SAX.h +204 -0
- data/ext/nokogiri/include/libxml2/libxml/SAX2.h +172 -0
- data/ext/nokogiri/include/libxml2/libxml/c14n.h +128 -0
- data/ext/nokogiri/include/libxml2/libxml/catalog.h +182 -0
- data/ext/nokogiri/include/libxml2/libxml/chvalid.h +230 -0
- data/ext/nokogiri/include/libxml2/libxml/debugXML.h +217 -0
- data/ext/nokogiri/include/libxml2/libxml/dict.h +81 -0
- data/ext/nokogiri/include/libxml2/libxml/encoding.h +232 -0
- data/ext/nokogiri/include/libxml2/libxml/entities.h +153 -0
- data/ext/nokogiri/include/libxml2/libxml/globals.h +499 -0
- data/ext/nokogiri/include/libxml2/libxml/hash.h +236 -0
- data/ext/nokogiri/include/libxml2/libxml/list.h +137 -0
- data/ext/nokogiri/include/libxml2/libxml/nanoftp.h +186 -0
- data/ext/nokogiri/include/libxml2/libxml/nanohttp.h +81 -0
- data/ext/nokogiri/include/libxml2/libxml/parser.h +1244 -0
- data/ext/nokogiri/include/libxml2/libxml/parserInternals.h +656 -0
- data/ext/nokogiri/include/libxml2/libxml/pattern.h +100 -0
- data/ext/nokogiri/include/libxml2/libxml/relaxng.h +218 -0
- data/ext/nokogiri/include/libxml2/libxml/schemasInternals.h +958 -0
- data/ext/nokogiri/include/libxml2/libxml/schematron.h +142 -0
- data/ext/nokogiri/include/libxml2/libxml/threads.h +91 -0
- data/ext/nokogiri/include/libxml2/libxml/tree.h +1312 -0
- data/ext/nokogiri/include/libxml2/libxml/uri.h +94 -0
- data/ext/nokogiri/include/libxml2/libxml/valid.h +463 -0
- data/ext/nokogiri/include/libxml2/libxml/xinclude.h +129 -0
- data/ext/nokogiri/include/libxml2/libxml/xlink.h +189 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlIO.h +368 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlautomata.h +146 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlerror.h +947 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlexports.h +77 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlmemory.h +226 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlmodule.h +57 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlreader.h +428 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlregexp.h +222 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlsave.h +88 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlschemas.h +246 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlschemastypes.h +152 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlstring.h +140 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlunicode.h +202 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlversion.h +503 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlwriter.h +488 -0
- data/ext/nokogiri/include/libxml2/libxml/xpath.h +575 -0
- data/ext/nokogiri/include/libxml2/libxml/xpathInternals.h +632 -0
- data/ext/nokogiri/include/libxml2/libxml/xpointer.h +137 -0
- data/ext/nokogiri/include/libxslt/attributes.h +38 -0
- data/ext/nokogiri/include/libxslt/documents.h +93 -0
- data/ext/nokogiri/include/libxslt/extensions.h +262 -0
- data/ext/nokogiri/include/libxslt/extra.h +72 -0
- data/ext/nokogiri/include/libxslt/functions.h +78 -0
- data/ext/nokogiri/include/libxslt/imports.h +75 -0
- data/ext/nokogiri/include/libxslt/keys.h +53 -0
- data/ext/nokogiri/include/libxslt/namespaces.h +68 -0
- data/ext/nokogiri/include/libxslt/numbersInternals.h +73 -0
- data/ext/nokogiri/include/libxslt/pattern.h +84 -0
- data/ext/nokogiri/include/libxslt/preproc.h +43 -0
- data/ext/nokogiri/include/libxslt/security.h +104 -0
- data/ext/nokogiri/include/libxslt/templates.h +77 -0
- data/ext/nokogiri/include/libxslt/transform.h +207 -0
- data/ext/nokogiri/include/libxslt/variables.h +118 -0
- data/ext/nokogiri/include/libxslt/xslt.h +110 -0
- data/ext/nokogiri/include/libxslt/xsltInternals.h +1982 -0
- data/ext/nokogiri/include/libxslt/xsltconfig.h +179 -0
- data/ext/nokogiri/include/libxslt/xsltexports.h +64 -0
- data/ext/nokogiri/include/libxslt/xsltlocale.h +76 -0
- data/ext/nokogiri/include/libxslt/xsltutils.h +310 -0
- data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
- data/ext/nokogiri/nokogiri.c +228 -104
- data/ext/nokogiri/nokogiri.h +204 -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 +15 -20
- data/ext/nokogiri/xml_comment.c +19 -26
- data/ext/nokogiri/xml_document.c +306 -225
- data/ext/nokogiri/xml_document_fragment.c +12 -16
- data/ext/nokogiri/xml_dtd.c +64 -58
- data/ext/nokogiri/xml_element_content.c +33 -28
- data/ext/nokogiri/xml_element_decl.c +26 -26
- data/ext/nokogiri/xml_encoding_handler.c +45 -20
- data/ext/nokogiri/xml_entity_decl.c +37 -35
- data/ext/nokogiri/xml_entity_reference.c +16 -18
- data/ext/nokogiri/xml_namespace.c +136 -61
- data/ext/nokogiri/xml_node.c +1344 -672
- data/ext/nokogiri/xml_node_set.c +178 -168
- data/ext/nokogiri/xml_processing_instruction.c +17 -19
- data/ext/nokogiri/xml_reader.c +316 -190
- data/ext/nokogiri/xml_relax_ng.c +52 -30
- data/ext/nokogiri/xml_sax_parser.c +130 -124
- data/ext/nokogiri/xml_sax_parser_context.c +110 -89
- data/ext/nokogiri/xml_sax_push_parser.c +36 -29
- data/ext/nokogiri/xml_schema.c +98 -50
- data/ext/nokogiri/xml_syntax_error.c +42 -21
- data/ext/nokogiri/xml_text.c +14 -18
- data/ext/nokogiri/xml_xpath_context.c +263 -148
- data/ext/nokogiri/xslt_stylesheet.c +271 -178
- data/gumbo-parser/CHANGES.md +63 -0
- data/gumbo-parser/Makefile +111 -0
- data/gumbo-parser/THANKS +27 -0
- data/lib/nokogiri/2.7/nokogiri.so +0 -0
- data/lib/nokogiri/3.0/nokogiri.so +0 -0
- data/lib/nokogiri/3.1/nokogiri.so +0 -0
- data/lib/nokogiri/3.2/nokogiri.so +0 -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 +5 -3
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +223 -94
- 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 +572 -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 +98 -0
- data/lib/nokogiri/html5.rb +389 -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 +3 -1
- data/lib/nokogiri/xml/builder.rb +75 -34
- 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 +2 -0
- data/lib/nokogiri/xml/element_decl.rb +3 -1
- data/lib/nokogiri/xml/entity_decl.rb +4 -2
- data/lib/nokogiri/xml/entity_reference.rb +2 -0
- data/lib/nokogiri/xml/namespace.rb +45 -0
- data/lib/nokogiri/xml/node/save_options.rb +15 -8
- data/lib/nokogiri/xml/node.rb +1067 -406
- data/lib/nokogiri/xml/node_set.rb +135 -59
- 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 +27 -26
- 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 +112 -72
- data/lib/nokogiri/xml/syntax_error.rb +6 -4
- data/lib/nokogiri/xml/text.rb +2 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
- data/lib/nokogiri/xml/xpath.rb +15 -4
- data/lib/nokogiri/xml/xpath_context.rb +3 -3
- data/lib/nokogiri/xml.rb +38 -37
- data/lib/nokogiri/xslt/stylesheet.rb +3 -1
- data/lib/nokogiri/xslt.rb +29 -20
- data/lib/nokogiri.rb +48 -72
- data/lib/xsd/xmlparser/nokogiri.rb +29 -25
- metadata +146 -307
- 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-Remove-script-macro-support.patch +0 -40
- data/patches/libxml2/0003-Update-entities-to-remove-handling-of-ssi.patch +0 -44
- data/patches/libxml2/0004-libxml2.la-is-in-top_builddir.patch +0 -25
- data/patches/libxml2/0005-Fix-infinite-loop-in-xmlStringLenDecodeEntities.patch +0 -32
- data/ports/archives/libxml2-2.9.10.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.34.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
|
+
"Nokogiri/XMLNode",
|
47
|
+
{_xml_node_mark, 0, 0, _xml_node_update_references},
|
48
|
+
0, 0,
|
49
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
50
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
51
|
+
#endif
|
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;
|
@@ -64,7 +89,9 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
64
89
|
if (reparented->type != XML_ELEMENT_NODE || !reparented->parent) { return; }
|
65
90
|
|
66
91
|
/* Make sure that our reparented node has the correct namespaces */
|
67
|
-
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)) {
|
68
95
|
xmlSetNs(reparented, reparented->parent->ns);
|
69
96
|
}
|
70
97
|
|
@@ -87,7 +114,7 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
87
114
|
} else {
|
88
115
|
reparented->nsDef = curr->next;
|
89
116
|
}
|
90
|
-
|
117
|
+
noko_xml_document_pin_namespace(curr, reparented->doc);
|
91
118
|
} else {
|
92
119
|
prev = curr;
|
93
120
|
}
|
@@ -127,16 +154,19 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
127
154
|
}
|
128
155
|
|
129
156
|
if (reparented->type == XML_ELEMENT_NODE) {
|
130
|
-
|
131
|
-
while(NULL !=
|
132
|
-
relink_namespace(
|
133
|
-
|
157
|
+
attr = reparented->properties;
|
158
|
+
while (NULL != attr) {
|
159
|
+
relink_namespace((xmlNodePtr)attr);
|
160
|
+
attr = attr->next;
|
134
161
|
}
|
135
162
|
}
|
136
163
|
}
|
137
164
|
|
138
|
-
|
139
|
-
|
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)
|
140
170
|
{
|
141
171
|
xmlNodePtr retval ;
|
142
172
|
|
@@ -159,22 +189,34 @@ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
|
|
159
189
|
return retval ;
|
160
190
|
}
|
161
191
|
|
162
|
-
|
163
|
-
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)
|
164
206
|
{
|
165
207
|
VALUE reparented_obj ;
|
166
|
-
xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text, parent ;
|
208
|
+
xmlNodePtr reparentee, original_reparentee, pivot, reparented, next_text, new_next_text, parent ;
|
167
209
|
int original_ns_prefix_is_default = 0 ;
|
168
210
|
|
169
|
-
if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
|
211
|
+
if (!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
|
170
212
|
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
|
171
213
|
}
|
172
|
-
if(rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
|
214
|
+
if (rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
|
173
215
|
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
|
174
216
|
}
|
175
217
|
|
176
|
-
|
177
|
-
|
218
|
+
Noko_Node_Get_Struct(reparentee_obj, xmlNode, reparentee);
|
219
|
+
Noko_Node_Get_Struct(pivot_obj, xmlNode, pivot);
|
178
220
|
|
179
221
|
/*
|
180
222
|
* Check if nodes given are appropriate to have a parent-child
|
@@ -190,66 +232,66 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
|
|
190
232
|
|
191
233
|
if (parent) {
|
192
234
|
switch (parent->type) {
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|
+
}
|
209
253
|
break;
|
210
|
-
|
211
|
-
break;
|
212
|
-
case XML_DOCUMENT_FRAG_NODE:
|
213
|
-
case XML_ENTITY_REF_NODE:
|
214
|
-
case XML_ELEMENT_NODE:
|
215
|
-
switch (reparentee->type) {
|
216
|
-
case XML_ELEMENT_NODE:
|
217
|
-
case XML_PI_NODE:
|
218
|
-
case XML_COMMENT_NODE:
|
219
|
-
case XML_TEXT_NODE:
|
220
|
-
case XML_CDATA_SECTION_NODE:
|
254
|
+
case XML_DOCUMENT_FRAG_NODE:
|
221
255
|
case XML_ENTITY_REF_NODE:
|
222
|
-
|
223
|
-
|
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
|
+
}
|
224
277
|
break;
|
225
|
-
}
|
226
|
-
break;
|
227
|
-
case XML_ATTRIBUTE_NODE:
|
228
|
-
switch (reparentee->type) {
|
229
278
|
case XML_TEXT_NODE:
|
230
|
-
|
231
|
-
|
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;
|
232
286
|
default:
|
233
287
|
break;
|
234
|
-
}
|
235
|
-
break;
|
236
|
-
case XML_TEXT_NODE:
|
237
|
-
/*
|
238
|
-
* xmlAddChild() breaks the DOM specification in that it allows
|
239
|
-
* adding a text node to another, in which case text nodes are
|
240
|
-
* coalesced, but since our JRuby version does not support such
|
241
|
-
* operation, we should inhibit it.
|
242
|
-
*/
|
243
|
-
break;
|
244
|
-
default:
|
245
|
-
break;
|
246
288
|
}
|
247
289
|
|
248
290
|
rb_raise(rb_eArgError, "cannot reparent %s there", rb_obj_classname(reparentee_obj));
|
249
291
|
}
|
250
292
|
|
251
293
|
ok:
|
252
|
-
|
294
|
+
original_reparentee = reparentee;
|
253
295
|
|
254
296
|
if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
|
255
297
|
/*
|
@@ -290,7 +332,7 @@ ok:
|
|
290
332
|
original_ns_prefix_is_default = 1;
|
291
333
|
}
|
292
334
|
|
293
|
-
|
335
|
+
noko_xml_document_pin_node(reparentee);
|
294
336
|
|
295
337
|
if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
|
296
338
|
rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
|
@@ -301,11 +343,13 @@ ok:
|
|
301
343
|
* issue #391, where new node's prefix may become the string "default"
|
302
344
|
* see libxml2 tree.c xmlNewReconciliedNs which implements this behavior.
|
303
345
|
*/
|
304
|
-
xmlFree(reparentee->ns->prefix);
|
346
|
+
xmlFree(DISCARD_CONST_QUAL_XMLCHAR(reparentee->ns->prefix));
|
305
347
|
reparentee->ns->prefix = NULL;
|
306
348
|
}
|
307
349
|
}
|
308
350
|
|
351
|
+
xmlUnlinkNode(original_reparentee);
|
352
|
+
|
309
353
|
if (prf != xmlAddPrevSibling && prf != xmlAddNextSibling
|
310
354
|
&& reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
|
311
355
|
/*
|
@@ -330,12 +374,12 @@ ok:
|
|
330
374
|
new_next_text = xmlDocCopyNode(next_text, pivot->doc, 1) ;
|
331
375
|
|
332
376
|
xmlUnlinkNode(next_text);
|
333
|
-
|
377
|
+
noko_xml_document_pin_node(next_text);
|
334
378
|
|
335
379
|
xmlAddNextSibling(pivot, new_next_text);
|
336
380
|
}
|
337
381
|
|
338
|
-
if(!(reparented = (*prf)(pivot, reparentee))) {
|
382
|
+
if (!(reparented = (*prf)(pivot, reparentee))) {
|
339
383
|
rb_raise(rb_eRuntimeError, "Could not reparent node");
|
340
384
|
}
|
341
385
|
|
@@ -345,57 +389,432 @@ ok:
|
|
345
389
|
* adjacent text nodes.
|
346
390
|
*/
|
347
391
|
DATA_PTR(reparentee_obj) = reparented ;
|
392
|
+
reparented_obj = noko_xml_node_wrap(Qnil, reparented);
|
348
393
|
|
349
|
-
|
394
|
+
rb_funcall(reparented_obj, id_decorate_bang, 0);
|
350
395
|
|
351
|
-
|
396
|
+
/* if we've created a cycle, raise an exception */
|
397
|
+
raise_if_ancestor_of_self(reparented);
|
352
398
|
|
353
|
-
|
399
|
+
relink_namespace(reparented);
|
354
400
|
|
355
401
|
return reparented_obj ;
|
356
402
|
}
|
357
403
|
|
404
|
+
// :startdoc:
|
358
405
|
|
359
406
|
/*
|
360
|
-
* call-seq:
|
361
|
-
*
|
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
|
362
778
|
*
|
363
|
-
*
|
779
|
+
* [Returns] Parent Nokogiri::XML::Document for this node
|
364
780
|
*/
|
365
|
-
static VALUE
|
781
|
+
static VALUE
|
782
|
+
rb_xml_node_document(VALUE self)
|
366
783
|
{
|
367
784
|
xmlNodePtr node;
|
368
|
-
|
785
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
369
786
|
return DOC_RUBY_OBJECT(node->doc);
|
370
787
|
}
|
371
788
|
|
372
789
|
/*
|
373
|
-
* call-seq:
|
374
|
-
* pointer_id
|
790
|
+
* :call-seq: pointer_id() → Integer
|
375
791
|
*
|
376
|
-
*
|
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.
|
377
795
|
*/
|
378
|
-
static VALUE
|
796
|
+
static VALUE
|
797
|
+
rb_xml_node_pointer_id(VALUE self)
|
379
798
|
{
|
380
799
|
xmlNodePtr node;
|
381
|
-
|
800
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
382
801
|
|
383
|
-
return
|
802
|
+
return rb_uint2inum((uintptr_t)(node));
|
384
803
|
}
|
385
804
|
|
386
805
|
/*
|
387
|
-
* call-seq:
|
388
|
-
* encode_special_chars(string)
|
806
|
+
* :call-seq: encode_special_chars(string) → String
|
389
807
|
*
|
390
808
|
* Encode any special characters in +string+
|
391
809
|
*/
|
392
|
-
static VALUE
|
810
|
+
static VALUE
|
811
|
+
encode_special_chars(VALUE self, VALUE string)
|
393
812
|
{
|
394
813
|
xmlNodePtr node;
|
395
814
|
xmlChar *encoded;
|
396
815
|
VALUE encoded_str;
|
397
816
|
|
398
|
-
|
817
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
399
818
|
encoded = xmlEncodeSpecialChars(
|
400
819
|
node->doc,
|
401
820
|
(const xmlChar *)StringValueCStr(string)
|
@@ -408,8 +827,8 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
|
|
408
827
|
}
|
409
828
|
|
410
829
|
/*
|
411
|
-
* call-seq:
|
412
|
-
*
|
830
|
+
* :call-seq:
|
831
|
+
* create_internal_subset(name, external_id, system_id)
|
413
832
|
*
|
414
833
|
* Create the internal subset of a document.
|
415
834
|
*
|
@@ -419,17 +838,18 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
|
|
419
838
|
* doc.create_internal_subset("chapter", nil, "chapter.dtd")
|
420
839
|
* # => <!DOCTYPE chapter SYSTEM "chapter.dtd">
|
421
840
|
*/
|
422
|
-
static VALUE
|
841
|
+
static VALUE
|
842
|
+
create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
|
423
843
|
{
|
424
844
|
xmlNodePtr node;
|
425
845
|
xmlDocPtr doc;
|
426
846
|
xmlDtdPtr dtd;
|
427
847
|
|
428
|
-
|
848
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
429
849
|
|
430
850
|
doc = node->doc;
|
431
851
|
|
432
|
-
if(xmlGetIntSubset(doc)) {
|
852
|
+
if (xmlGetIntSubset(doc)) {
|
433
853
|
rb_raise(rb_eRuntimeError, "Document already has an internal subset");
|
434
854
|
}
|
435
855
|
|
@@ -440,28 +860,29 @@ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, V
|
|
440
860
|
NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
|
441
861
|
);
|
442
862
|
|
443
|
-
if(!dtd) { return Qnil; }
|
863
|
+
if (!dtd) { return Qnil; }
|
444
864
|
|
445
|
-
return
|
865
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
446
866
|
}
|
447
867
|
|
448
868
|
/*
|
449
|
-
* call-seq:
|
450
|
-
*
|
869
|
+
* :call-seq:
|
870
|
+
* create_external_subset(name, external_id, system_id)
|
451
871
|
*
|
452
872
|
* Create an external subset
|
453
873
|
*/
|
454
|
-
static VALUE
|
874
|
+
static VALUE
|
875
|
+
create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
|
455
876
|
{
|
456
877
|
xmlNodePtr node;
|
457
878
|
xmlDocPtr doc;
|
458
879
|
xmlDtdPtr dtd;
|
459
880
|
|
460
|
-
|
881
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
461
882
|
|
462
883
|
doc = node->doc;
|
463
884
|
|
464
|
-
if(doc->extSubset) {
|
885
|
+
if (doc->extSubset) {
|
465
886
|
rb_raise(rb_eRuntimeError, "Document already has an external subset");
|
466
887
|
}
|
467
888
|
|
@@ -472,72 +893,78 @@ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, V
|
|
472
893
|
NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
|
473
894
|
);
|
474
895
|
|
475
|
-
if(!dtd) { return Qnil; }
|
896
|
+
if (!dtd) { return Qnil; }
|
476
897
|
|
477
|
-
return
|
898
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
478
899
|
}
|
479
900
|
|
480
901
|
/*
|
481
|
-
* call-seq:
|
482
|
-
*
|
902
|
+
* :call-seq:
|
903
|
+
* external_subset()
|
483
904
|
*
|
484
905
|
* Get the external subset
|
485
906
|
*/
|
486
|
-
static VALUE
|
907
|
+
static VALUE
|
908
|
+
external_subset(VALUE self)
|
487
909
|
{
|
488
910
|
xmlNodePtr node;
|
489
911
|
xmlDocPtr doc;
|
490
912
|
xmlDtdPtr dtd;
|
491
913
|
|
492
|
-
|
914
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
493
915
|
|
494
|
-
if(!node->doc) { return Qnil; }
|
916
|
+
if (!node->doc) { return Qnil; }
|
495
917
|
|
496
918
|
doc = node->doc;
|
497
919
|
dtd = doc->extSubset;
|
498
920
|
|
499
|
-
if(!dtd) { return Qnil; }
|
921
|
+
if (!dtd) { return Qnil; }
|
500
922
|
|
501
|
-
return
|
923
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
502
924
|
}
|
503
925
|
|
504
926
|
/*
|
505
|
-
* call-seq:
|
506
|
-
*
|
927
|
+
* :call-seq:
|
928
|
+
* internal_subset()
|
507
929
|
*
|
508
930
|
* Get the internal subset
|
509
931
|
*/
|
510
|
-
static VALUE
|
932
|
+
static VALUE
|
933
|
+
internal_subset(VALUE self)
|
511
934
|
{
|
512
935
|
xmlNodePtr node;
|
513
936
|
xmlDocPtr doc;
|
514
937
|
xmlDtdPtr dtd;
|
515
938
|
|
516
|
-
|
939
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
517
940
|
|
518
|
-
if(!node->doc) { return Qnil; }
|
941
|
+
if (!node->doc) { return Qnil; }
|
519
942
|
|
520
943
|
doc = node->doc;
|
521
944
|
dtd = xmlGetIntSubset(doc);
|
522
945
|
|
523
|
-
if(!dtd) { return Qnil; }
|
946
|
+
if (!dtd) { return Qnil; }
|
524
947
|
|
525
|
-
return
|
948
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
|
526
949
|
}
|
527
950
|
|
528
951
|
/*
|
529
|
-
* call-seq:
|
530
|
-
*
|
531
|
-
*
|
532
|
-
*
|
952
|
+
* :call-seq:
|
953
|
+
* dup → Nokogiri::XML::Node
|
954
|
+
* dup(depth) → Nokogiri::XML::Node
|
955
|
+
* dup(depth, new_parent_doc) → Nokogiri::XML::Node
|
533
956
|
*
|
534
957
|
* Copy this node.
|
535
|
-
*
|
536
|
-
*
|
537
|
-
*
|
538
|
-
*
|
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
|
539
965
|
*/
|
540
|
-
static VALUE
|
966
|
+
static VALUE
|
967
|
+
duplicate_node(int argc, VALUE *argv, VALUE self)
|
541
968
|
{
|
542
969
|
VALUE r_level, r_new_parent_doc;
|
543
970
|
int level;
|
@@ -545,7 +972,7 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
545
972
|
xmlDocPtr new_parent_doc;
|
546
973
|
xmlNodePtr node, dup;
|
547
974
|
|
548
|
-
|
975
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
549
976
|
|
550
977
|
n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
|
551
978
|
|
@@ -561,40 +988,29 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
561
988
|
}
|
562
989
|
|
563
990
|
dup = xmlDocCopyNode(node, new_parent_doc, level);
|
564
|
-
if(dup == NULL) { return Qnil; }
|
991
|
+
if (dup == NULL) { return Qnil; }
|
565
992
|
|
566
|
-
|
993
|
+
noko_xml_document_pin_node(dup);
|
567
994
|
|
568
|
-
return
|
995
|
+
return noko_xml_node_wrap(rb_obj_class(self), dup);
|
569
996
|
}
|
570
997
|
|
571
998
|
/*
|
572
|
-
* call-seq:
|
573
|
-
*
|
999
|
+
* :call-seq:
|
1000
|
+
* unlink() → self
|
574
1001
|
*
|
575
1002
|
* Unlink this node from its current context.
|
576
1003
|
*/
|
577
|
-
static VALUE
|
1004
|
+
static VALUE
|
1005
|
+
unlink_node(VALUE self)
|
578
1006
|
{
|
579
1007
|
xmlNodePtr node;
|
580
|
-
|
1008
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
581
1009
|
xmlUnlinkNode(node);
|
582
|
-
|
1010
|
+
noko_xml_document_pin_node(node);
|
583
1011
|
return self;
|
584
1012
|
}
|
585
1013
|
|
586
|
-
/*
|
587
|
-
* call-seq:
|
588
|
-
* blank?
|
589
|
-
*
|
590
|
-
* Is this node blank?
|
591
|
-
*/
|
592
|
-
static VALUE blank_eh(VALUE self)
|
593
|
-
{
|
594
|
-
xmlNodePtr node;
|
595
|
-
Data_Get_Struct(self, xmlNode, node);
|
596
|
-
return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
|
597
|
-
}
|
598
1014
|
|
599
1015
|
/*
|
600
1016
|
* call-seq:
|
@@ -602,15 +1018,16 @@ static VALUE blank_eh(VALUE self)
|
|
602
1018
|
*
|
603
1019
|
* Returns the next sibling node
|
604
1020
|
*/
|
605
|
-
static VALUE
|
1021
|
+
static VALUE
|
1022
|
+
next_sibling(VALUE self)
|
606
1023
|
{
|
607
1024
|
xmlNodePtr node, sibling;
|
608
|
-
|
1025
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
609
1026
|
|
610
1027
|
sibling = node->next;
|
611
|
-
if(!sibling) { return Qnil; }
|
1028
|
+
if (!sibling) { return Qnil; }
|
612
1029
|
|
613
|
-
return
|
1030
|
+
return noko_xml_node_wrap(Qnil, sibling) ;
|
614
1031
|
}
|
615
1032
|
|
616
1033
|
/*
|
@@ -619,15 +1036,16 @@ static VALUE next_sibling(VALUE self)
|
|
619
1036
|
*
|
620
1037
|
* Returns the previous sibling node
|
621
1038
|
*/
|
622
|
-
static VALUE
|
1039
|
+
static VALUE
|
1040
|
+
previous_sibling(VALUE self)
|
623
1041
|
{
|
624
1042
|
xmlNodePtr node, sibling;
|
625
|
-
|
1043
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
626
1044
|
|
627
1045
|
sibling = node->prev;
|
628
|
-
if(!sibling) { return Qnil; }
|
1046
|
+
if (!sibling) { return Qnil; }
|
629
1047
|
|
630
|
-
return
|
1048
|
+
return noko_xml_node_wrap(Qnil, sibling);
|
631
1049
|
}
|
632
1050
|
|
633
1051
|
/*
|
@@ -636,15 +1054,16 @@ static VALUE previous_sibling(VALUE self)
|
|
636
1054
|
*
|
637
1055
|
* Returns the next Nokogiri::XML::Element type sibling node.
|
638
1056
|
*/
|
639
|
-
static VALUE
|
1057
|
+
static VALUE
|
1058
|
+
next_element(VALUE self)
|
640
1059
|
{
|
641
1060
|
xmlNodePtr node, sibling;
|
642
|
-
|
1061
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
643
1062
|
|
644
1063
|
sibling = xmlNextElementSibling(node);
|
645
|
-
if(!sibling) { return Qnil; }
|
1064
|
+
if (!sibling) { return Qnil; }
|
646
1065
|
|
647
|
-
return
|
1066
|
+
return noko_xml_node_wrap(Qnil, sibling);
|
648
1067
|
}
|
649
1068
|
|
650
1069
|
/*
|
@@ -653,82 +1072,60 @@ static VALUE next_element(VALUE self)
|
|
653
1072
|
*
|
654
1073
|
* Returns the previous Nokogiri::XML::Element type sibling node.
|
655
1074
|
*/
|
656
|
-
static VALUE
|
1075
|
+
static VALUE
|
1076
|
+
previous_element(VALUE self)
|
657
1077
|
{
|
658
1078
|
xmlNodePtr node, sibling;
|
659
|
-
|
1079
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
660
1080
|
|
661
1081
|
/*
|
662
1082
|
* note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
|
663
1083
|
*/
|
664
1084
|
sibling = node->prev;
|
665
|
-
if(!sibling) { return Qnil; }
|
1085
|
+
if (!sibling) { return Qnil; }
|
666
1086
|
|
667
|
-
while(sibling && sibling->type != XML_ELEMENT_NODE) {
|
1087
|
+
while (sibling && sibling->type != XML_ELEMENT_NODE) {
|
668
1088
|
sibling = sibling->prev;
|
669
1089
|
}
|
670
1090
|
|
671
|
-
return sibling ?
|
1091
|
+
return sibling ? noko_xml_node_wrap(Qnil, sibling) : Qnil ;
|
672
1092
|
}
|
673
1093
|
|
674
1094
|
/* :nodoc: */
|
675
|
-
static VALUE
|
1095
|
+
static VALUE
|
1096
|
+
replace(VALUE self, VALUE new_node)
|
676
1097
|
{
|
677
1098
|
VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
|
678
1099
|
|
679
1100
|
xmlNodePtr pivot;
|
680
|
-
|
681
|
-
|
1101
|
+
Noko_Node_Get_Struct(self, xmlNode, pivot);
|
1102
|
+
noko_xml_document_pin_node(pivot);
|
682
1103
|
|
683
1104
|
return reparent;
|
684
1105
|
}
|
685
1106
|
|
686
1107
|
/*
|
687
|
-
* call-seq:
|
688
|
-
*
|
1108
|
+
* :call-seq:
|
1109
|
+
* element_children() → NodeSet
|
1110
|
+
* elements() → NodeSet
|
689
1111
|
*
|
690
|
-
*
|
691
|
-
|
692
|
-
|
693
|
-
{
|
694
|
-
xmlNodePtr node;
|
695
|
-
xmlNodePtr child;
|
696
|
-
xmlNodeSetPtr set;
|
697
|
-
VALUE document;
|
698
|
-
VALUE node_set;
|
699
|
-
|
700
|
-
Data_Get_Struct(self, xmlNode, node);
|
701
|
-
|
702
|
-
child = node->children;
|
703
|
-
set = xmlXPathNodeSetCreate(child);
|
704
|
-
|
705
|
-
document = DOC_RUBY_OBJECT(node->doc);
|
706
|
-
|
707
|
-
if(!child) { return Nokogiri_wrap_xml_node_set(set, document); }
|
708
|
-
|
709
|
-
child = child->next;
|
710
|
-
while(NULL != child) {
|
711
|
-
xmlXPathNodeSetAddUnique(set, child);
|
712
|
-
child = child->next;
|
713
|
-
}
|
714
|
-
|
715
|
-
node_set = Nokogiri_wrap_xml_node_set(set, document);
|
716
|
-
|
717
|
-
return node_set;
|
718
|
-
}
|
719
|
-
|
720
|
-
/*
|
721
|
-
* call-seq:
|
722
|
-
* element_children
|
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.
|
723
1115
|
*
|
724
|
-
*
|
725
|
-
* element nodes.
|
1116
|
+
* *Example:*
|
726
1117
|
*
|
727
|
-
*
|
1118
|
+
* Note that #children returns the Text node "hello" while #element_children does not.
|
728
1119
|
*
|
729
|
-
*
|
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">]>]
|
730
1126
|
*/
|
731
|
-
static VALUE
|
1127
|
+
static VALUE
|
1128
|
+
rb_xml_node_element_children(VALUE self)
|
732
1129
|
{
|
733
1130
|
xmlNodePtr node;
|
734
1131
|
xmlNodePtr child;
|
@@ -736,83 +1133,78 @@ static VALUE element_children(VALUE self)
|
|
736
1133
|
VALUE document;
|
737
1134
|
VALUE node_set;
|
738
1135
|
|
739
|
-
|
1136
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
740
1137
|
|
741
1138
|
child = xmlFirstElementChild(node);
|
742
1139
|
set = xmlXPathNodeSetCreate(child);
|
743
1140
|
|
744
1141
|
document = DOC_RUBY_OBJECT(node->doc);
|
745
1142
|
|
746
|
-
if(!child) { return
|
747
|
-
|
748
|
-
child = xmlNextElementSibling(child);
|
749
|
-
while(NULL != child) {
|
750
|
-
xmlXPathNodeSetAddUnique(set, child);
|
751
|
-
child = xmlNextElementSibling(child);
|
752
|
-
}
|
753
|
-
|
754
|
-
node_set = Nokogiri_wrap_xml_node_set(set, document);
|
1143
|
+
if (!child) { return noko_xml_node_set_wrap(set, document); }
|
755
1144
|
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
* child
|
762
|
-
*
|
763
|
-
* Returns the child node
|
764
|
-
*/
|
765
|
-
static VALUE child(VALUE self)
|
766
|
-
{
|
767
|
-
xmlNodePtr node, child;
|
768
|
-
Data_Get_Struct(self, xmlNode, node);
|
1145
|
+
child = xmlNextElementSibling(child);
|
1146
|
+
while (NULL != child) {
|
1147
|
+
xmlXPathNodeSetAddUnique(set, child);
|
1148
|
+
child = xmlNextElementSibling(child);
|
1149
|
+
}
|
769
1150
|
|
770
|
-
|
771
|
-
if(!child) { return Qnil; }
|
1151
|
+
node_set = noko_xml_node_set_wrap(set, document);
|
772
1152
|
|
773
|
-
return
|
1153
|
+
return node_set;
|
774
1154
|
}
|
775
1155
|
|
776
1156
|
/*
|
777
|
-
* call-seq:
|
778
|
-
*
|
1157
|
+
* :call-seq:
|
1158
|
+
* first_element_child() → Node
|
779
1159
|
*
|
780
|
-
* Returns
|
1160
|
+
* [Returns] The first child Node that is an element.
|
781
1161
|
*
|
782
|
-
* Example
|
1162
|
+
* *Example:*
|
783
1163
|
*
|
784
|
-
*
|
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")] })
|
785
1170
|
*/
|
786
|
-
static VALUE
|
1171
|
+
static VALUE
|
1172
|
+
rb_xml_node_first_element_child(VALUE self)
|
787
1173
|
{
|
788
1174
|
xmlNodePtr node, child;
|
789
|
-
|
1175
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
790
1176
|
|
791
1177
|
child = xmlFirstElementChild(node);
|
792
|
-
if(!child) { return Qnil; }
|
1178
|
+
if (!child) { return Qnil; }
|
793
1179
|
|
794
|
-
return
|
1180
|
+
return noko_xml_node_wrap(Qnil, child);
|
795
1181
|
}
|
796
1182
|
|
797
1183
|
/*
|
798
|
-
* call-seq:
|
799
|
-
*
|
1184
|
+
* :call-seq:
|
1185
|
+
* last_element_child() → Node
|
800
1186
|
*
|
801
|
-
* Returns
|
1187
|
+
* [Returns] The last child Node that is an element.
|
802
1188
|
*
|
803
|
-
* Example
|
1189
|
+
* *Example:*
|
804
1190
|
*
|
805
|
-
*
|
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")] })
|
806
1197
|
*/
|
807
|
-
static VALUE
|
1198
|
+
static VALUE
|
1199
|
+
rb_xml_node_last_element_child(VALUE self)
|
808
1200
|
{
|
809
1201
|
xmlNodePtr node, child;
|
810
|
-
|
1202
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
811
1203
|
|
812
1204
|
child = xmlLastElementChild(node);
|
813
|
-
if(!child) { return Qnil; }
|
1205
|
+
if (!child) { return Qnil; }
|
814
1206
|
|
815
|
-
return
|
1207
|
+
return noko_xml_node_wrap(Qnil, child);
|
816
1208
|
}
|
817
1209
|
|
818
1210
|
/*
|
@@ -821,11 +1213,12 @@ static VALUE last_element_child(VALUE self)
|
|
821
1213
|
*
|
822
1214
|
* Returns true if +attribute+ is set
|
823
1215
|
*/
|
824
|
-
static VALUE
|
1216
|
+
static VALUE
|
1217
|
+
key_eh(VALUE self, VALUE attribute)
|
825
1218
|
{
|
826
1219
|
xmlNodePtr node;
|
827
|
-
|
828
|
-
if(xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
|
1220
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1221
|
+
if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
|
829
1222
|
return Qtrue;
|
830
1223
|
}
|
831
1224
|
return Qfalse;
|
@@ -837,12 +1230,13 @@ static VALUE key_eh(VALUE self, VALUE attribute)
|
|
837
1230
|
*
|
838
1231
|
* Returns true if +attribute+ is set with +namespace+
|
839
1232
|
*/
|
840
|
-
static VALUE
|
1233
|
+
static VALUE
|
1234
|
+
namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
|
841
1235
|
{
|
842
1236
|
xmlNodePtr node;
|
843
|
-
|
844
|
-
if(xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
|
845
|
-
|
1237
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1238
|
+
if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
|
1239
|
+
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
|
846
1240
|
return Qtrue;
|
847
1241
|
}
|
848
1242
|
return Qfalse;
|
@@ -854,11 +1248,12 @@ static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
|
|
854
1248
|
*
|
855
1249
|
* Set the +property+ to +value+
|
856
1250
|
*/
|
857
|
-
static VALUE
|
1251
|
+
static VALUE
|
1252
|
+
set(VALUE self, VALUE property, VALUE value)
|
858
1253
|
{
|
859
1254
|
xmlNodePtr node, cur;
|
860
1255
|
xmlAttrPtr prop;
|
861
|
-
|
1256
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
862
1257
|
|
863
1258
|
/* If a matching attribute node already exists, then xmlSetProp will destroy
|
864
1259
|
* the existing node's children. However, if Nokogiri has a node object
|
@@ -867,13 +1262,13 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
|
|
867
1262
|
* We can avoid this by unlinking these nodes first.
|
868
1263
|
*/
|
869
1264
|
if (node->type != XML_ELEMENT_NODE) {
|
870
|
-
return(Qnil);
|
1265
|
+
return (Qnil);
|
871
1266
|
}
|
872
1267
|
prop = xmlHasProp(node, (xmlChar *)StringValueCStr(property));
|
873
1268
|
if (prop && prop->children) {
|
874
1269
|
for (cur = prop->children; cur; cur = cur->next) {
|
875
1270
|
if (cur->_private) {
|
876
|
-
|
1271
|
+
noko_xml_document_pin_node(cur);
|
877
1272
|
xmlUnlinkNode(cur);
|
878
1273
|
}
|
879
1274
|
}
|
@@ -891,7 +1286,8 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
|
|
891
1286
|
*
|
892
1287
|
* Get the value for +attribute+
|
893
1288
|
*/
|
894
|
-
static VALUE
|
1289
|
+
static VALUE
|
1290
|
+
get(VALUE self, VALUE rattribute)
|
895
1291
|
{
|
896
1292
|
xmlNodePtr node;
|
897
1293
|
xmlChar *value = 0;
|
@@ -902,10 +1298,10 @@ static VALUE get(VALUE self, VALUE rattribute)
|
|
902
1298
|
|
903
1299
|
if (NIL_P(rattribute)) { return Qnil; }
|
904
1300
|
|
905
|
-
|
1301
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
906
1302
|
attribute = xmlCharStrdup(StringValueCStr(rattribute));
|
907
1303
|
|
908
|
-
colon = (
|
1304
|
+
colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
|
909
1305
|
if (colon) {
|
910
1306
|
/* split the attribute string into separate prefix and name by
|
911
1307
|
* null-terminating the prefix at the colon */
|
@@ -917,7 +1313,7 @@ static VALUE get(VALUE self, VALUE rattribute)
|
|
917
1313
|
if (ns) {
|
918
1314
|
value = xmlGetNsProp(node, attr_name, ns->href);
|
919
1315
|
} else {
|
920
|
-
value = xmlGetProp(node, (xmlChar*)StringValueCStr(rattribute));
|
1316
|
+
value = xmlGetProp(node, (xmlChar *)StringValueCStr(rattribute));
|
921
1317
|
}
|
922
1318
|
} else {
|
923
1319
|
value = xmlGetNoNsProp(node, attribute);
|
@@ -938,15 +1334,16 @@ static VALUE get(VALUE self, VALUE rattribute)
|
|
938
1334
|
*
|
939
1335
|
* Set the namespace to +namespace+
|
940
1336
|
*/
|
941
|
-
static VALUE
|
1337
|
+
static VALUE
|
1338
|
+
set_namespace(VALUE self, VALUE namespace)
|
942
1339
|
{
|
943
1340
|
xmlNodePtr node;
|
944
1341
|
xmlNsPtr ns = NULL;
|
945
1342
|
|
946
|
-
|
1343
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
947
1344
|
|
948
|
-
if(!NIL_P(namespace)) {
|
949
|
-
|
1345
|
+
if (!NIL_P(namespace)) {
|
1346
|
+
Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
|
950
1347
|
}
|
951
1348
|
|
952
1349
|
xmlSetNs(node, ns);
|
@@ -955,138 +1352,140 @@ static VALUE set_namespace(VALUE self, VALUE namespace)
|
|
955
1352
|
}
|
956
1353
|
|
957
1354
|
/*
|
958
|
-
* call-seq:
|
959
|
-
*
|
1355
|
+
* :call-seq:
|
1356
|
+
* namespace() → Namespace
|
960
1357
|
*
|
961
|
-
*
|
962
|
-
*/
|
963
|
-
static VALUE attr(VALUE self, VALUE name)
|
964
|
-
{
|
965
|
-
xmlNodePtr node;
|
966
|
-
xmlAttrPtr prop;
|
967
|
-
Data_Get_Struct(self, xmlNode, node);
|
968
|
-
prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
|
969
|
-
|
970
|
-
if(! prop) { return Qnil; }
|
971
|
-
return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
|
972
|
-
}
|
973
|
-
|
974
|
-
/*
|
975
|
-
* call-seq:
|
976
|
-
* attribute_with_ns(name, namespace)
|
1358
|
+
* [Returns] The Namespace of the element or attribute node, or +nil+ if there is no namespace.
|
977
1359
|
*
|
978
|
-
*
|
979
|
-
*/
|
980
|
-
static VALUE attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
|
981
|
-
{
|
982
|
-
xmlNodePtr node;
|
983
|
-
xmlAttrPtr prop;
|
984
|
-
Data_Get_Struct(self, xmlNode, node);
|
985
|
-
prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
|
986
|
-
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
|
987
|
-
|
988
|
-
if(! prop) { return Qnil; }
|
989
|
-
return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
|
990
|
-
}
|
991
|
-
|
992
|
-
/*
|
993
|
-
* call-seq:
|
994
|
-
* attribute_nodes()
|
1360
|
+
* *Example:*
|
995
1361
|
*
|
996
|
-
*
|
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" })
|
997
1375
|
*/
|
998
|
-
static VALUE
|
1376
|
+
static VALUE
|
1377
|
+
rb_xml_node_namespace(VALUE rb_node)
|
999
1378
|
{
|
1000
|
-
|
1001
|
-
|
1002
|
-
VALUE attr;
|
1379
|
+
xmlNodePtr c_node ;
|
1380
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1003
1381
|
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
Nokogiri_xml_node_properties(node, attr);
|
1382
|
+
if (c_node->ns) {
|
1383
|
+
return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
|
1384
|
+
}
|
1008
1385
|
|
1009
|
-
return
|
1386
|
+
return Qnil ;
|
1010
1387
|
}
|
1011
1388
|
|
1012
|
-
|
1013
1389
|
/*
|
1014
|
-
*
|
1015
|
-
*
|
1390
|
+
* :call-seq:
|
1391
|
+
* namespace_definitions() → Array<Nokogiri::XML::Namespace>
|
1016
1392
|
*
|
1017
|
-
*
|
1018
|
-
*
|
1019
|
-
|
1020
|
-
static VALUE namespace(VALUE self)
|
1021
|
-
{
|
1022
|
-
xmlNodePtr node ;
|
1023
|
-
Data_Get_Struct(self, xmlNode, node);
|
1024
|
-
|
1025
|
-
if (node->ns) {
|
1026
|
-
return Nokogiri_wrap_xml_namespace(node->doc, node->ns);
|
1027
|
-
}
|
1028
|
-
|
1029
|
-
return Qnil ;
|
1030
|
-
}
|
1031
|
-
|
1032
|
-
/*
|
1033
|
-
* call-seq:
|
1034
|
-
* namespace_definitions()
|
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.
|
1035
1396
|
*
|
1036
|
-
*
|
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" })]
|
1037
1416
|
*/
|
1038
|
-
static VALUE
|
1417
|
+
static VALUE
|
1418
|
+
namespace_definitions(VALUE rb_node)
|
1039
1419
|
{
|
1040
1420
|
/* this code in the mode of xmlHasProp() */
|
1041
|
-
xmlNodePtr
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
Data_Get_Struct(self, xmlNode, node);
|
1421
|
+
xmlNodePtr c_node ;
|
1422
|
+
xmlNsPtr c_namespace;
|
1423
|
+
VALUE definitions = rb_ary_new();
|
1046
1424
|
|
1047
|
-
|
1425
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1048
1426
|
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1427
|
+
c_namespace = c_node->nsDef;
|
1428
|
+
if (!c_namespace) {
|
1429
|
+
return definitions;
|
1430
|
+
}
|
1052
1431
|
|
1053
|
-
while(
|
1054
|
-
rb_ary_push(
|
1055
|
-
|
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;
|
1056
1435
|
}
|
1057
1436
|
|
1058
|
-
return
|
1437
|
+
return definitions;
|
1059
1438
|
}
|
1060
1439
|
|
1061
1440
|
/*
|
1062
|
-
*
|
1063
|
-
*
|
1441
|
+
* :call-seq:
|
1442
|
+
* namespace_scopes() → Array<Nokogiri::XML::Namespace>
|
1064
1443
|
*
|
1065
|
-
*
|
1066
|
-
*
|
1067
|
-
*
|
1068
|
-
*
|
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" })]
|
1069
1467
|
*/
|
1070
|
-
static VALUE
|
1468
|
+
static VALUE
|
1469
|
+
rb_xml_node_namespace_scopes(VALUE rb_node)
|
1071
1470
|
{
|
1072
|
-
xmlNodePtr
|
1073
|
-
|
1074
|
-
|
1471
|
+
xmlNodePtr c_node ;
|
1472
|
+
xmlNsPtr *namespaces;
|
1473
|
+
VALUE scopes = rb_ary_new();
|
1075
1474
|
int j;
|
1076
1475
|
|
1077
|
-
|
1476
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1078
1477
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1478
|
+
namespaces = xmlGetNsList(c_node->doc, c_node);
|
1479
|
+
if (!namespaces) {
|
1480
|
+
return scopes;
|
1481
|
+
}
|
1083
1482
|
|
1084
|
-
for (j = 0 ;
|
1085
|
-
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));
|
1086
1485
|
}
|
1087
1486
|
|
1088
|
-
xmlFree(
|
1089
|
-
return
|
1487
|
+
xmlFree(namespaces);
|
1488
|
+
return scopes;
|
1090
1489
|
}
|
1091
1490
|
|
1092
1491
|
/*
|
@@ -1095,11 +1494,12 @@ static VALUE namespace_scopes(VALUE self)
|
|
1095
1494
|
*
|
1096
1495
|
* Get the type for this Node
|
1097
1496
|
*/
|
1098
|
-
static VALUE
|
1497
|
+
static VALUE
|
1498
|
+
node_type(VALUE self)
|
1099
1499
|
{
|
1100
1500
|
xmlNodePtr node;
|
1101
|
-
|
1102
|
-
return INT2NUM(
|
1501
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1502
|
+
return INT2NUM(node->type);
|
1103
1503
|
}
|
1104
1504
|
|
1105
1505
|
/*
|
@@ -1108,16 +1508,17 @@ static VALUE node_type(VALUE self)
|
|
1108
1508
|
*
|
1109
1509
|
* Set the content for this Node
|
1110
1510
|
*/
|
1111
|
-
static VALUE
|
1511
|
+
static VALUE
|
1512
|
+
set_native_content(VALUE self, VALUE content)
|
1112
1513
|
{
|
1113
1514
|
xmlNodePtr node, child, next ;
|
1114
|
-
|
1515
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1115
1516
|
|
1116
1517
|
child = node->children;
|
1117
1518
|
while (NULL != child) {
|
1118
1519
|
next = child->next ;
|
1119
1520
|
xmlUnlinkNode(child) ;
|
1120
|
-
|
1521
|
+
noko_xml_document_pin_node(child);
|
1121
1522
|
child = next ;
|
1122
1523
|
}
|
1123
1524
|
|
@@ -1125,42 +1526,20 @@ static VALUE set_native_content(VALUE self, VALUE content)
|
|
1125
1526
|
return content;
|
1126
1527
|
}
|
1127
1528
|
|
1128
|
-
/*
|
1129
|
-
* call-seq:
|
1130
|
-
* content
|
1131
|
-
*
|
1132
|
-
* Returns the plaintext content for this Node. Note that entities will always
|
1133
|
-
* be expanded in the returned string.
|
1134
|
-
*/
|
1135
|
-
static VALUE get_native_content(VALUE self)
|
1136
|
-
{
|
1137
|
-
xmlNodePtr node;
|
1138
|
-
xmlChar * content;
|
1139
|
-
|
1140
|
-
Data_Get_Struct(self, xmlNode, node);
|
1141
|
-
|
1142
|
-
content = xmlNodeGetContent(node);
|
1143
|
-
if(content) {
|
1144
|
-
VALUE rval = NOKOGIRI_STR_NEW2(content);
|
1145
|
-
xmlFree(content);
|
1146
|
-
return rval;
|
1147
|
-
}
|
1148
|
-
return Qnil;
|
1149
|
-
}
|
1150
|
-
|
1151
1529
|
/*
|
1152
1530
|
* call-seq:
|
1153
1531
|
* lang=
|
1154
1532
|
*
|
1155
1533
|
* Set the language of a node, i.e. the values of the xml:lang attribute.
|
1156
1534
|
*/
|
1157
|
-
static VALUE
|
1535
|
+
static VALUE
|
1536
|
+
set_lang(VALUE self_rb, VALUE lang_rb)
|
1158
1537
|
{
|
1159
1538
|
xmlNodePtr self ;
|
1160
|
-
xmlChar*
|
1539
|
+
xmlChar *lang ;
|
1161
1540
|
|
1162
|
-
|
1163
|
-
lang = (xmlChar*)StringValueCStr(lang_rb);
|
1541
|
+
Noko_Node_Get_Struct(self_rb, xmlNode, self);
|
1542
|
+
lang = (xmlChar *)StringValueCStr(lang_rb);
|
1164
1543
|
|
1165
1544
|
xmlNodeSetLang(self, lang);
|
1166
1545
|
|
@@ -1174,13 +1553,14 @@ static VALUE set_lang(VALUE self_rb, VALUE lang_rb)
|
|
1174
1553
|
* Searches the language of a node, i.e. the values of the xml:lang attribute or
|
1175
1554
|
* the one carried by the nearest ancestor.
|
1176
1555
|
*/
|
1177
|
-
static VALUE
|
1556
|
+
static VALUE
|
1557
|
+
get_lang(VALUE self_rb)
|
1178
1558
|
{
|
1179
1559
|
xmlNodePtr self ;
|
1180
|
-
xmlChar*
|
1560
|
+
xmlChar *lang ;
|
1181
1561
|
VALUE lang_rb ;
|
1182
1562
|
|
1183
|
-
|
1563
|
+
Noko_Node_Get_Struct(self_rb, xmlNode, self);
|
1184
1564
|
|
1185
1565
|
lang = xmlNodeGetLang(self);
|
1186
1566
|
if (lang) {
|
@@ -1193,7 +1573,8 @@ static VALUE get_lang(VALUE self_rb)
|
|
1193
1573
|
}
|
1194
1574
|
|
1195
1575
|
/* :nodoc: */
|
1196
|
-
static VALUE
|
1576
|
+
static VALUE
|
1577
|
+
add_child(VALUE self, VALUE new_child)
|
1197
1578
|
{
|
1198
1579
|
return reparent_node_with(self, new_child, xmlAddChild);
|
1199
1580
|
}
|
@@ -1204,15 +1585,16 @@ static VALUE add_child(VALUE self, VALUE new_child)
|
|
1204
1585
|
*
|
1205
1586
|
* Get the parent Node for this Node
|
1206
1587
|
*/
|
1207
|
-
static VALUE
|
1588
|
+
static VALUE
|
1589
|
+
get_parent(VALUE self)
|
1208
1590
|
{
|
1209
1591
|
xmlNodePtr node, parent;
|
1210
|
-
|
1592
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1211
1593
|
|
1212
1594
|
parent = node->parent;
|
1213
|
-
if(!parent) { return Qnil; }
|
1595
|
+
if (!parent) { return Qnil; }
|
1214
1596
|
|
1215
|
-
return
|
1597
|
+
return noko_xml_node_wrap(Qnil, parent) ;
|
1216
1598
|
}
|
1217
1599
|
|
1218
1600
|
/*
|
@@ -1221,11 +1603,12 @@ static VALUE get_parent(VALUE self)
|
|
1221
1603
|
*
|
1222
1604
|
* Set the name for this Node
|
1223
1605
|
*/
|
1224
|
-
static VALUE
|
1606
|
+
static VALUE
|
1607
|
+
set_name(VALUE self, VALUE new_name)
|
1225
1608
|
{
|
1226
1609
|
xmlNodePtr node;
|
1227
|
-
|
1228
|
-
xmlNodeSetName(node, (xmlChar*)StringValueCStr(new_name));
|
1610
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1611
|
+
xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
|
1229
1612
|
return new_name;
|
1230
1613
|
}
|
1231
1614
|
|
@@ -1235,11 +1618,12 @@ static VALUE set_name(VALUE self, VALUE new_name)
|
|
1235
1618
|
*
|
1236
1619
|
* Returns the name for this Node
|
1237
1620
|
*/
|
1238
|
-
static VALUE
|
1621
|
+
static VALUE
|
1622
|
+
get_name(VALUE self)
|
1239
1623
|
{
|
1240
1624
|
xmlNodePtr node;
|
1241
|
-
|
1242
|
-
if(node->name) {
|
1625
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1626
|
+
if (node->name) {
|
1243
1627
|
return NOKOGIRI_STR_NEW2(node->name);
|
1244
1628
|
}
|
1245
1629
|
return Qnil;
|
@@ -1251,28 +1635,39 @@ static VALUE get_name(VALUE self)
|
|
1251
1635
|
*
|
1252
1636
|
* Returns the path associated with this Node
|
1253
1637
|
*/
|
1254
|
-
static VALUE
|
1638
|
+
static VALUE
|
1639
|
+
rb_xml_node_path(VALUE rb_node)
|
1255
1640
|
{
|
1256
|
-
xmlNodePtr
|
1257
|
-
xmlChar *
|
1641
|
+
xmlNodePtr c_node;
|
1642
|
+
xmlChar *c_path ;
|
1258
1643
|
VALUE rval;
|
1259
1644
|
|
1260
|
-
|
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
|
+
}
|
1261
1657
|
|
1262
|
-
path = xmlGetNodePath(node);
|
1263
|
-
rval = NOKOGIRI_STR_NEW2(path);
|
1264
|
-
xmlFree(path);
|
1265
1658
|
return rval ;
|
1266
1659
|
}
|
1267
1660
|
|
1268
1661
|
/* :nodoc: */
|
1269
|
-
static VALUE
|
1662
|
+
static VALUE
|
1663
|
+
add_next_sibling(VALUE self, VALUE new_sibling)
|
1270
1664
|
{
|
1271
1665
|
return reparent_node_with(self, new_sibling, xmlAddNextSibling) ;
|
1272
1666
|
}
|
1273
1667
|
|
1274
1668
|
/* :nodoc: */
|
1275
|
-
static VALUE
|
1669
|
+
static VALUE
|
1670
|
+
add_previous_sibling(VALUE self, VALUE new_sibling)
|
1276
1671
|
{
|
1277
1672
|
return reparent_node_with(self, new_sibling, xmlAddPrevSibling) ;
|
1278
1673
|
}
|
@@ -1283,7 +1678,8 @@ static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
|
|
1283
1678
|
*
|
1284
1679
|
* Write this Node to +io+ with +encoding+ and +options+
|
1285
1680
|
*/
|
1286
|
-
static VALUE
|
1681
|
+
static VALUE
|
1682
|
+
native_write_to(
|
1287
1683
|
VALUE self,
|
1288
1684
|
VALUE io,
|
1289
1685
|
VALUE encoding,
|
@@ -1292,10 +1688,10 @@ static VALUE native_write_to(
|
|
1292
1688
|
)
|
1293
1689
|
{
|
1294
1690
|
xmlNodePtr node;
|
1295
|
-
const char *
|
1691
|
+
const char *before_indent;
|
1296
1692
|
xmlSaveCtxtPtr savectx;
|
1297
1693
|
|
1298
|
-
|
1694
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1299
1695
|
|
1300
1696
|
xmlIndentTreeOutput = 1;
|
1301
1697
|
|
@@ -1304,8 +1700,8 @@ static VALUE native_write_to(
|
|
1304
1700
|
xmlTreeIndentString = StringValueCStr(indent_string);
|
1305
1701
|
|
1306
1702
|
savectx = xmlSaveToIO(
|
1307
|
-
(xmlOutputWriteCallback)
|
1308
|
-
(xmlOutputCloseCallback)
|
1703
|
+
(xmlOutputWriteCallback)noko_io_write,
|
1704
|
+
(xmlOutputCloseCallback)noko_io_close,
|
1309
1705
|
(void *)io,
|
1310
1706
|
RTEST(encoding) ? StringValueCStr(encoding) : NULL,
|
1311
1707
|
(int)NUM2INT(options)
|
@@ -1318,93 +1714,366 @@ static VALUE native_write_to(
|
|
1318
1714
|
return io;
|
1319
1715
|
}
|
1320
1716
|
|
1321
|
-
|
1322
|
-
|
1323
|
-
*
|
1324
|
-
*
|
1325
|
-
* Returns the line for this Node
|
1326
|
-
*/
|
1327
|
-
static VALUE line(VALUE self)
|
1717
|
+
|
1718
|
+
static inline void
|
1719
|
+
output_partial_string(VALUE out, char const *str, size_t length)
|
1328
1720
|
{
|
1329
|
-
|
1330
|
-
|
1721
|
+
if (length) {
|
1722
|
+
rb_enc_str_buf_cat(out, str, (long)length, rb_utf8_encoding());
|
1723
|
+
}
|
1724
|
+
}
|
1331
1725
|
|
1332
|
-
|
1726
|
+
static inline void
|
1727
|
+
output_char(VALUE out, char ch)
|
1728
|
+
{
|
1729
|
+
output_partial_string(out, &ch, 1);
|
1333
1730
|
}
|
1334
1731
|
|
1335
|
-
|
1336
|
-
*
|
1337
|
-
* add_namespace_definition(prefix, href)
|
1338
|
-
*
|
1339
|
-
* Adds a namespace definition with +prefix+ using +href+ value. The result is
|
1340
|
-
* as if parsed XML for this node had included an attribute
|
1341
|
-
* 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
|
1342
|
-
* added by passing 'nil' for prefix. Namespaces added this way will not
|
1343
|
-
* show up in #attributes, but they will be included as an xmlns attribute
|
1344
|
-
* when the node is serialized to XML.
|
1345
|
-
*/
|
1346
|
-
static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
|
1732
|
+
static inline void
|
1733
|
+
output_string(VALUE out, char const *str)
|
1347
1734
|
{
|
1348
|
-
|
1349
|
-
|
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
|
+
}
|
1350
1827
|
|
1351
|
-
|
1352
|
-
|
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
|
+
}
|
1353
1840
|
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
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
|
+
}
|
1359
1848
|
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
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;
|
1363
1859
|
}
|
1364
|
-
ns = xmlNewNs(
|
1365
|
-
namespace,
|
1366
|
-
(const xmlChar *)StringValueCStr(href),
|
1367
|
-
(const xmlChar *)(NIL_P(prefix) ? NULL : StringValueCStr(prefix))
|
1368
|
-
);
|
1369
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
|
+
}
|
1370
1966
|
|
1371
|
-
|
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
|
+
}
|
1372
1979
|
|
1373
|
-
|
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);
|
1374
2012
|
|
1375
|
-
return
|
2013
|
+
return LONG2NUM(xmlGetLineNo(c_node));
|
1376
2014
|
}
|
1377
2015
|
|
1378
2016
|
/*
|
1379
2017
|
* call-seq:
|
1380
|
-
*
|
2018
|
+
* line=(num)
|
1381
2019
|
*
|
1382
|
-
*
|
2020
|
+
* Sets the line for this Node. num must be less than 65535.
|
1383
2021
|
*/
|
1384
|
-
static VALUE
|
2022
|
+
static VALUE
|
2023
|
+
rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
|
1385
2024
|
{
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
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;
|
1390
2052
|
VALUE rest;
|
1391
2053
|
VALUE rb_node;
|
1392
2054
|
|
1393
|
-
rb_scan_args(argc, argv, "2*", &
|
2055
|
+
rb_scan_args(argc, argv, "2*", &rb_name, &rb_document_node, &rest);
|
1394
2056
|
|
1395
|
-
|
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);
|
1396
2065
|
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
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);
|
1400
2069
|
|
1401
|
-
rb_node =
|
2070
|
+
rb_node = noko_xml_node_wrap(
|
1402
2071
|
klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
|
1403
|
-
|
2072
|
+
c_node
|
1404
2073
|
);
|
1405
2074
|
rb_obj_call_init(rb_node, argc, argv);
|
1406
2075
|
|
1407
|
-
if(rb_block_given_p()) { rb_yield(rb_node); }
|
2076
|
+
if (rb_block_given_p()) { rb_yield(rb_node); }
|
1408
2077
|
|
1409
2078
|
return rb_node;
|
1410
2079
|
}
|
@@ -1415,13 +2084,14 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
|
|
1415
2084
|
*
|
1416
2085
|
* Returns the Node as html.
|
1417
2086
|
*/
|
1418
|
-
static VALUE
|
2087
|
+
static VALUE
|
2088
|
+
dump_html(VALUE self)
|
1419
2089
|
{
|
1420
2090
|
xmlBufferPtr buf ;
|
1421
2091
|
xmlNodePtr node ;
|
1422
2092
|
VALUE html;
|
1423
2093
|
|
1424
|
-
|
2094
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1425
2095
|
|
1426
2096
|
buf = xmlBufferCreate() ;
|
1427
2097
|
htmlNodeDump(buf, node->doc, node);
|
@@ -1436,13 +2106,14 @@ static VALUE dump_html(VALUE self)
|
|
1436
2106
|
*
|
1437
2107
|
* Compare this Node to +other+ with respect to their Document
|
1438
2108
|
*/
|
1439
|
-
static VALUE
|
2109
|
+
static VALUE
|
2110
|
+
compare(VALUE self, VALUE _other)
|
1440
2111
|
{
|
1441
2112
|
xmlNodePtr node, other;
|
1442
|
-
|
1443
|
-
|
2113
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
2114
|
+
Noko_Node_Get_Struct(_other, xmlNode, other);
|
1444
2115
|
|
1445
|
-
return INT2NUM(
|
2116
|
+
return INT2NUM(xmlXPathCmpNodes(other, node));
|
1446
2117
|
}
|
1447
2118
|
|
1448
2119
|
|
@@ -1453,13 +2124,14 @@ static VALUE compare(VALUE self, VALUE _other)
|
|
1453
2124
|
* Loads and substitutes all xinclude elements below the node. The
|
1454
2125
|
* parser context will be initialized with +options+.
|
1455
2126
|
*/
|
1456
|
-
static VALUE
|
2127
|
+
static VALUE
|
2128
|
+
process_xincludes(VALUE self, VALUE options)
|
1457
2129
|
{
|
1458
2130
|
int rcode ;
|
1459
2131
|
xmlNodePtr node;
|
1460
2132
|
VALUE error_list = rb_ary_new();
|
1461
2133
|
|
1462
|
-
|
2134
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1463
2135
|
|
1464
2136
|
xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
|
1465
2137
|
rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
|
@@ -1469,7 +2141,7 @@ static VALUE process_xincludes(VALUE self, VALUE options)
|
|
1469
2141
|
xmlErrorPtr error;
|
1470
2142
|
|
1471
2143
|
error = xmlGetLastError();
|
1472
|
-
if(error) {
|
2144
|
+
if (error) {
|
1473
2145
|
rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
|
1474
2146
|
} else {
|
1475
2147
|
rb_raise(rb_eRuntimeError, "Could not perform xinclude substitution");
|
@@ -1481,7 +2153,8 @@ static VALUE process_xincludes(VALUE self, VALUE options)
|
|
1481
2153
|
|
1482
2154
|
|
1483
2155
|
/* TODO: DOCUMENT ME */
|
1484
|
-
static VALUE
|
2156
|
+
static VALUE
|
2157
|
+
in_context(VALUE self, VALUE _str, VALUE _options)
|
1485
2158
|
{
|
1486
2159
|
xmlNodePtr node, list = 0, tmp, child_iter, node_children, doc_children;
|
1487
2160
|
xmlNodeSetPtr set;
|
@@ -1489,7 +2162,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1489
2162
|
VALUE doc, err;
|
1490
2163
|
int doc_is_empty;
|
1491
2164
|
|
1492
|
-
|
2165
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1493
2166
|
|
1494
2167
|
doc = DOC_RUBY_OBJECT(node->doc);
|
1495
2168
|
err = rb_iv_get(doc, "@errors");
|
@@ -1530,9 +2203,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1530
2203
|
*/
|
1531
2204
|
child_iter = node->doc->children ;
|
1532
2205
|
while (child_iter) {
|
1533
|
-
|
1534
|
-
child_iter->parent = (xmlNodePtr)node->doc;
|
1535
|
-
}
|
2206
|
+
child_iter->parent = (xmlNodePtr)node->doc;
|
1536
2207
|
child_iter = child_iter->next;
|
1537
2208
|
}
|
1538
2209
|
|
@@ -1542,12 +2213,17 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1542
2213
|
|
1543
2214
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
1544
2215
|
|
1545
|
-
/*
|
2216
|
+
/*
|
2217
|
+
* Workaround for a libxml2 bug where a parsing error may leave a broken
|
1546
2218
|
* node reference in node->doc->children.
|
2219
|
+
*
|
2220
|
+
* https://bugzilla.gnome.org/show_bug.cgi?id=668155
|
2221
|
+
*
|
1547
2222
|
* This workaround is limited to when a parse error occurs, the document
|
1548
2223
|
* went from having no children to having children, and the context node is
|
1549
2224
|
* part of a document fragment.
|
1550
|
-
*
|
2225
|
+
*
|
2226
|
+
* TODO: This was fixed in libxml 2.8.0 by 71a243d
|
1551
2227
|
*/
|
1552
2228
|
if (error != XML_ERR_OK && doc_is_empty && node->doc->children != NULL) {
|
1553
2229
|
child_iter = node;
|
@@ -1562,12 +2238,12 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1562
2238
|
|
1563
2239
|
/* FIXME: This probably needs to handle more constants... */
|
1564
2240
|
switch (error) {
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
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;
|
1571
2247
|
}
|
1572
2248
|
|
1573
2249
|
set = xmlXPathNodeSetCreate(NULL);
|
@@ -1576,178 +2252,174 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1576
2252
|
tmp = list->next;
|
1577
2253
|
list->next = NULL;
|
1578
2254
|
xmlXPathNodeSetAddUnique(set, list);
|
1579
|
-
|
2255
|
+
noko_xml_document_pin_node(list);
|
1580
2256
|
list = tmp;
|
1581
2257
|
}
|
1582
2258
|
|
1583
|
-
return
|
2259
|
+
return noko_xml_node_set_wrap(set, doc);
|
1584
2260
|
}
|
1585
2261
|
|
1586
|
-
|
1587
|
-
|
2262
|
+
VALUE
|
2263
|
+
noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
|
1588
2264
|
{
|
1589
|
-
VALUE
|
1590
|
-
VALUE node_cache = Qnil ;
|
1591
|
-
VALUE rb_node = Qnil ;
|
2265
|
+
VALUE rb_document, rb_node_cache, rb_node;
|
1592
2266
|
nokogiriTuplePtr node_has_a_document;
|
1593
|
-
xmlDocPtr
|
1594
|
-
void (*mark_method)(xmlNodePtr) = NULL ;
|
2267
|
+
xmlDocPtr c_doc;
|
1595
2268
|
|
1596
|
-
assert(
|
2269
|
+
assert(c_node);
|
1597
2270
|
|
1598
|
-
if(
|
1599
|
-
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);
|
1600
2273
|
}
|
1601
2274
|
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
if (doc->type == XML_DOCUMENT_FRAG_NODE) { doc = doc->doc; }
|
1607
|
-
node_has_a_document = DOC_RUBY_OBJECT_TEST(doc);
|
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);
|
1608
2279
|
|
1609
|
-
if(
|
1610
|
-
return (VALUE)
|
2280
|
+
if (c_node->_private && node_has_a_document) {
|
2281
|
+
return (VALUE)c_node->_private;
|
1611
2282
|
}
|
1612
2283
|
|
1613
|
-
if(!RTEST(
|
1614
|
-
switch(
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
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;
|
1653
2324
|
}
|
1654
2325
|
}
|
1655
2326
|
|
1656
|
-
|
1657
|
-
|
1658
|
-
rb_node = Data_Wrap_Struct(klass, mark_method, debug_node_dealloc, node) ;
|
1659
|
-
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;
|
1660
2329
|
|
1661
2330
|
if (node_has_a_document) {
|
1662
|
-
|
1663
|
-
|
1664
|
-
rb_ary_push(
|
1665
|
-
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);
|
1666
2335
|
}
|
1667
2336
|
|
1668
2337
|
return rb_node ;
|
1669
2338
|
}
|
1670
2339
|
|
1671
2340
|
|
1672
|
-
|
2341
|
+
/*
|
2342
|
+
* return Array<Nokogiri::XML::Attr> containing the node's attributes
|
2343
|
+
*/
|
2344
|
+
VALUE
|
2345
|
+
noko_xml_node_attrs(xmlNodePtr c_node)
|
1673
2346
|
{
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
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 ;
|
1679
2354
|
}
|
2355
|
+
|
2356
|
+
return rb_properties;
|
1680
2357
|
}
|
1681
2358
|
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
cNokogiriXmlNode
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
rb_define_method(
|
1698
|
-
rb_define_method(
|
1699
|
-
rb_define_method(
|
1700
|
-
rb_define_method(
|
1701
|
-
rb_define_method(
|
1702
|
-
rb_define_method(
|
1703
|
-
rb_define_method(
|
1704
|
-
rb_define_method(
|
1705
|
-
rb_define_method(
|
1706
|
-
rb_define_method(
|
1707
|
-
rb_define_method(
|
1708
|
-
rb_define_method(
|
1709
|
-
rb_define_method(
|
1710
|
-
rb_define_method(
|
1711
|
-
rb_define_method(
|
1712
|
-
rb_define_method(
|
1713
|
-
rb_define_method(
|
1714
|
-
rb_define_method(
|
1715
|
-
rb_define_method(
|
1716
|
-
rb_define_method(
|
1717
|
-
rb_define_method(
|
1718
|
-
rb_define_method(
|
1719
|
-
rb_define_method(
|
1720
|
-
rb_define_method(
|
1721
|
-
rb_define_method(
|
1722
|
-
rb_define_method(
|
1723
|
-
rb_define_method(
|
1724
|
-
rb_define_method(
|
1725
|
-
rb_define_method(
|
1726
|
-
rb_define_method(
|
1727
|
-
rb_define_method(
|
1728
|
-
rb_define_method(
|
1729
|
-
rb_define_method(
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
rb_define_private_method(
|
1737
|
-
rb_define_private_method(
|
1738
|
-
rb_define_private_method(
|
1739
|
-
rb_define_private_method(
|
1740
|
-
rb_define_private_method(
|
1741
|
-
rb_define_private_method(
|
1742
|
-
rb_define_private_method(
|
1743
|
-
rb_define_private_method(
|
1744
|
-
rb_define_private_method(
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
decorate = rb_intern("decorate");
|
1750
|
-
decorate_bang = rb_intern("decorate!");
|
1751
|
-
}
|
1752
|
-
|
1753
|
-
/* 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
|
+
}
|