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