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