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