nokogiri 1.11.3 → 1.13.8
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 +2 -0
- data/LICENSE-DEPENDENCIES.md +243 -22
- data/LICENSE.md +1 -1
- data/README.md +14 -11
- data/bin/nokogiri +63 -50
- data/dependencies.yml +13 -64
- data/ext/nokogiri/depend +35 -34
- data/ext/nokogiri/extconf.rb +237 -133
- data/ext/nokogiri/gumbo.c +584 -0
- data/ext/nokogiri/{html_document.c → html4_document.c} +8 -8
- data/ext/nokogiri/{html_element_description.c → html4_element_description.c} +21 -19
- data/ext/nokogiri/{html_entity_lookup.c → html4_entity_lookup.c} +7 -7
- data/ext/nokogiri/{html_sax_parser_context.c → html4_sax_parser_context.c} +8 -8
- data/ext/nokogiri/{html_sax_push_parser.c → html4_sax_push_parser.c} +4 -4
- data/ext/nokogiri/libxml2_backwards_compat.c +30 -30
- data/ext/nokogiri/nokogiri.c +70 -38
- data/ext/nokogiri/nokogiri.h +27 -9
- data/ext/nokogiri/xml_attr.c +2 -2
- data/ext/nokogiri/xml_attribute_decl.c +3 -3
- data/ext/nokogiri/xml_cdata.c +1 -1
- data/ext/nokogiri/xml_document.c +50 -50
- data/ext/nokogiri/xml_document_fragment.c +0 -2
- data/ext/nokogiri/xml_dtd.c +10 -10
- data/ext/nokogiri/xml_element_content.c +2 -0
- data/ext/nokogiri/xml_element_decl.c +3 -3
- data/ext/nokogiri/xml_encoding_handler.c +31 -12
- data/ext/nokogiri/xml_entity_decl.c +5 -5
- data/ext/nokogiri/xml_namespace.c +4 -2
- data/ext/nokogiri/xml_node.c +833 -492
- data/ext/nokogiri/xml_node_set.c +24 -24
- data/ext/nokogiri/xml_reader.c +90 -11
- data/ext/nokogiri/xml_sax_parser.c +6 -6
- data/ext/nokogiri/xml_sax_parser_context.c +12 -3
- data/ext/nokogiri/xml_schema.c +5 -3
- data/ext/nokogiri/xml_text.c +1 -1
- data/ext/nokogiri/xml_xpath_context.c +110 -85
- data/ext/nokogiri/xslt_stylesheet.c +109 -10
- 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 +9 -8
- data/lib/nokogiri/css/parser.rb +361 -342
- data/lib/nokogiri/css/parser.y +250 -245
- data/lib/nokogiri/css/parser_extras.rb +22 -20
- data/lib/nokogiri/css/syntax_error.rb +2 -1
- data/lib/nokogiri/css/tokenizer.rb +4 -3
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +179 -82
- data/lib/nokogiri/css.rb +49 -17
- data/lib/nokogiri/decorators/slop.rb +8 -7
- data/lib/nokogiri/extension.rb +8 -3
- data/lib/nokogiri/gumbo.rb +15 -0
- data/lib/nokogiri/html.rb +37 -27
- data/lib/nokogiri/{html → html4}/builder.rb +3 -2
- data/lib/nokogiri/{html → html4}/document.rb +92 -81
- data/lib/nokogiri/{html → html4}/document_fragment.rb +13 -9
- data/lib/nokogiri/{html → html4}/element_description.rb +2 -1
- data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
- data/lib/nokogiri/{html → html4}/entity_lookup.rb +3 -2
- data/lib/nokogiri/{html → html4}/sax/parser.rb +16 -16
- data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
- data/lib/nokogiri/{html → html4}/sax/push_parser.rb +11 -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 +10 -9
- data/lib/nokogiri/syntax_error.rb +1 -0
- data/lib/nokogiri/version/constant.rb +2 -1
- data/lib/nokogiri/version/info.rb +31 -14
- data/lib/nokogiri/version.rb +1 -0
- data/lib/nokogiri/xml/attr.rb +5 -3
- data/lib/nokogiri/xml/attribute_decl.rb +2 -1
- data/lib/nokogiri/xml/builder.rb +71 -31
- data/lib/nokogiri/xml/cdata.rb +2 -1
- data/lib/nokogiri/xml/character_data.rb +1 -0
- data/lib/nokogiri/xml/document.rb +183 -96
- data/lib/nokogiri/xml/document_fragment.rb +41 -38
- data/lib/nokogiri/xml/dtd.rb +3 -2
- data/lib/nokogiri/xml/element_content.rb +1 -0
- data/lib/nokogiri/xml/element_decl.rb +2 -1
- data/lib/nokogiri/xml/entity_decl.rb +3 -2
- data/lib/nokogiri/xml/entity_reference.rb +1 -0
- data/lib/nokogiri/xml/namespace.rb +2 -0
- data/lib/nokogiri/xml/node/save_options.rb +9 -5
- data/lib/nokogiri/xml/node.rb +525 -354
- data/lib/nokogiri/xml/node_set.rb +50 -54
- data/lib/nokogiri/xml/notation.rb +12 -0
- data/lib/nokogiri/xml/parse_options.rb +13 -6
- data/lib/nokogiri/xml/pp/character_data.rb +8 -6
- data/lib/nokogiri/xml/pp/node.rb +24 -26
- data/lib/nokogiri/xml/pp.rb +3 -2
- data/lib/nokogiri/xml/processing_instruction.rb +2 -1
- data/lib/nokogiri/xml/reader.rb +20 -24
- data/lib/nokogiri/xml/relax_ng.rb +1 -0
- data/lib/nokogiri/xml/sax/document.rb +44 -49
- data/lib/nokogiri/xml/sax/parser.rb +37 -34
- data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
- data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
- data/lib/nokogiri/xml/sax.rb +5 -4
- data/lib/nokogiri/xml/schema.rb +7 -6
- data/lib/nokogiri/xml/searchable.rb +93 -62
- data/lib/nokogiri/xml/syntax_error.rb +5 -4
- data/lib/nokogiri/xml/text.rb +1 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
- data/lib/nokogiri/xml/xpath.rb +13 -1
- data/lib/nokogiri/xml/xpath_context.rb +2 -3
- data/lib/nokogiri/xml.rb +37 -37
- data/lib/nokogiri/xslt/stylesheet.rb +2 -1
- data/lib/nokogiri/xslt.rb +28 -20
- data/lib/nokogiri.rb +48 -43
- data/lib/xsd/xmlparser/nokogiri.rb +25 -24
- data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
- data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
- data/patches/libxml2/{0004-libxml2.la-is-in-top_builddir.patch → 0003-libxml2.la-is-in-top_builddir.patch} +1 -1
- data/patches/libxml2/{0008-use-glibc-strlen.patch → 0004-use-glibc-strlen.patch} +3 -3
- data/patches/libxml2/{0009-avoid-isnan-isinf.patch → 0005-avoid-isnan-isinf.patch} +4 -4
- 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 +2445 -1919
- data/ports/archives/libxml2-2.9.14.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
- metadata +204 -93
- data/lib/nokogiri/html/element_description_defaults.rb +0 -672
- data/lib/nokogiri/html/sax/parser_context.rb +0 -17
- data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
- data/patches/libxml2/0005-Fix-infinite-loop-in-xmlStringLenDecodeEntities.patch +0 -32
- data/patches/libxml2/0006-htmlParseComment-treat-as-if-it-closed-the-comment.patch +0 -73
- data/patches/libxml2/0007-use-new-htmlParseLookupCommentEnd-to-find-comment-en.patch +0 -103
- data/patches/libxml2/0010-parser.c-shrink-the-input-buffer-when-appropriate.patch +0 -70
- data/patches/libxml2/0011-update-automake-files-for-arm64.patch +0 -2511
- data/ports/archives/libxml2-2.9.10.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
data/lib/nokogiri/xml/node.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
# encoding:
|
1
|
+
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require "stringio"
|
4
|
-
require "nokogiri/xml/node/save_options"
|
5
5
|
|
6
6
|
module Nokogiri
|
7
7
|
module XML
|
8
|
-
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# Nokogiri::XML::Node is the primary API you'll use to interact with your Document.
|
9
|
+
#
|
10
|
+
# == Attributes
|
11
|
+
#
|
12
|
+
# A Nokogiri::XML::Node may be treated similarly to a hash with regard to attributes. For
|
11
13
|
# example:
|
12
14
|
#
|
13
15
|
# node = Nokogiri::XML::DocumentFragment.parse("<a href='#foo' id='link'>link</a>").at_css("a")
|
@@ -18,41 +20,52 @@ module Nokogiri
|
|
18
20
|
# node['class'] = 'green' # => "green"
|
19
21
|
# node.to_html # => "<a href=\"#foo\" id=\"link\" class=\"green\">link</a>"
|
20
22
|
#
|
21
|
-
# See the method group entitled
|
23
|
+
# See the method group entitled Node@Working+With+Node+Attributes for the full set of methods.
|
24
|
+
#
|
25
|
+
# == Navigation
|
22
26
|
#
|
23
|
-
#
|
24
|
-
# tree. For navigating your tree, see:
|
27
|
+
# Nokogiri::XML::Node also has methods that let you move around your tree:
|
25
28
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# * {#next}
|
29
|
-
# * {#previous}
|
29
|
+
# [#parent, #children, #next, #previous]
|
30
|
+
# Navigate up, down, or through siblings.
|
30
31
|
#
|
31
|
-
#
|
32
|
-
# its subtree), there are a few methods you might want to use:
|
32
|
+
# See the method group entitled Node@Traversing+Document+Structure for the full set of methods.
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
34
|
+
# == Serialization
|
35
|
+
#
|
36
|
+
# When printing or otherwise emitting a document or a node (and its subtree), there are a few
|
37
|
+
# methods you might want to use:
|
38
|
+
#
|
39
|
+
# [#content, #text, #inner_text, #to_str]
|
40
|
+
# These methods will all **emit plaintext**,
|
41
|
+
# meaning that entities will be replaced (e.g., +<+ will be replaced with +<+), meaning
|
36
42
|
# that any sanitizing will likely be un-done in the output.
|
37
43
|
#
|
38
|
-
#
|
39
|
-
# properly-escaped markup
|
40
|
-
# parsers, etc.
|
44
|
+
# [#to_s, #to_xml, #to_html, #inner_html]
|
45
|
+
# These methods will all **emit properly-escaped markup**, meaning that it's suitable for
|
46
|
+
# consumption by browsers, parsers, etc.
|
47
|
+
#
|
48
|
+
# See the method group entitled Node@Serialization+and+Generating+Output for the full set of methods.
|
49
|
+
#
|
50
|
+
# == Searching
|
41
51
|
#
|
42
|
-
# You may search this node's subtree using
|
52
|
+
# You may search this node's subtree using methods like #xpath and #css.
|
53
|
+
#
|
54
|
+
# See the method group entitled Node@Searching+via+XPath+or+CSS+Queries for the full set of methods.
|
43
55
|
#
|
44
56
|
class Node
|
45
57
|
include Nokogiri::XML::PP::Node
|
46
58
|
include Nokogiri::XML::Searchable
|
59
|
+
include Nokogiri::ClassResolver
|
47
60
|
include Enumerable
|
48
61
|
|
49
|
-
# Element node type, see
|
62
|
+
# Element node type, see Nokogiri::XML::Node#element?
|
50
63
|
ELEMENT_NODE = 1
|
51
64
|
# Attribute node type
|
52
65
|
ATTRIBUTE_NODE = 2
|
53
|
-
# Text node type, see
|
66
|
+
# Text node type, see Nokogiri::XML::Node#text?
|
54
67
|
TEXT_NODE = 3
|
55
|
-
# CDATA node type, see
|
68
|
+
# CDATA node type, see Nokogiri::XML::Node#cdata?
|
56
69
|
CDATA_SECTION_NODE = 4
|
57
70
|
# Entity reference node type
|
58
71
|
ENTITY_REF_NODE = 5
|
@@ -60,9 +73,9 @@ module Nokogiri
|
|
60
73
|
ENTITY_NODE = 6
|
61
74
|
# PI node type
|
62
75
|
PI_NODE = 7
|
63
|
-
# Comment node type, see
|
76
|
+
# Comment node type, see Nokogiri::XML::Node#comment?
|
64
77
|
COMMENT_NODE = 8
|
65
|
-
# Document node type, see
|
78
|
+
# Document node type, see Nokogiri::XML::Node#xml?
|
66
79
|
DOCUMENT_NODE = 9
|
67
80
|
# Document type node type
|
68
81
|
DOCUMENT_TYPE_NODE = 10
|
@@ -70,7 +83,7 @@ module Nokogiri
|
|
70
83
|
DOCUMENT_FRAG_NODE = 11
|
71
84
|
# Notation node type
|
72
85
|
NOTATION_NODE = 12
|
73
|
-
# HTML document node type, see
|
86
|
+
# HTML document node type, see Nokogiri::XML::Node#html?
|
74
87
|
HTML_DOCUMENT_NODE = 13
|
75
88
|
# DTD node type
|
76
89
|
DTD_NODE = 14
|
@@ -89,15 +102,29 @@ module Nokogiri
|
|
89
102
|
# DOCB document node type
|
90
103
|
DOCB_DOCUMENT_NODE = 21
|
91
104
|
|
92
|
-
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
105
|
+
#
|
106
|
+
# :call-seq:
|
107
|
+
# new(name, document) -> Nokogiri::XML::Node
|
108
|
+
# new(name, document) { |node| ... } -> Nokogiri::XML::Node
|
109
|
+
#
|
110
|
+
# Create a new node with +name+ that belongs to +document+.
|
111
|
+
#
|
112
|
+
# If you intend to add a node to a document tree, it's likely that you will prefer one of the
|
113
|
+
# Nokogiri::XML::Node methods like #add_child, #add_next_sibling, #replace, etc. which will
|
114
|
+
# both create an element (or subtree) and place it in the document tree.
|
115
|
+
#
|
116
|
+
# Another alternative, if you are concerned about performance, is
|
117
|
+
# Nokogiri::XML::Document#create_element which accepts additional arguments for contents or
|
118
|
+
# attributes but (like this method) avoids parsing markup.
|
119
|
+
#
|
120
|
+
# [Parameters]
|
121
|
+
# - +name+ (String)
|
122
|
+
# - +document+ (Nokogiri::XML::Document) The document to which the the returned node will belong.
|
123
|
+
# [Yields] Nokogiri::XML::Node
|
124
|
+
# [Returns] Nokogiri::XML::Node
|
125
|
+
#
|
99
126
|
def initialize(name, document)
|
100
|
-
# This is intentionally empty.
|
127
|
+
# This is intentionally empty, and sets the method signature for subclasses.
|
101
128
|
end
|
102
129
|
|
103
130
|
###
|
@@ -106,18 +133,7 @@ module Nokogiri
|
|
106
133
|
document.decorate(self)
|
107
134
|
end
|
108
135
|
|
109
|
-
#
|
110
|
-
|
111
|
-
###
|
112
|
-
# Search this node's immediate children using CSS selector +selector+
|
113
|
-
def >(selector)
|
114
|
-
ns = document.root.namespaces
|
115
|
-
xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first
|
116
|
-
end
|
117
|
-
|
118
|
-
# @!endgroup
|
119
|
-
|
120
|
-
# @!group Manipulating Document Structure
|
136
|
+
# :section: Manipulating Document Structure
|
121
137
|
|
122
138
|
###
|
123
139
|
# Add +node_or_tags+ as a child of this Node.
|
@@ -129,9 +145,9 @@ module Nokogiri
|
|
129
145
|
def add_child(node_or_tags)
|
130
146
|
node_or_tags = coerce(node_or_tags)
|
131
147
|
if node_or_tags.is_a?(XML::NodeSet)
|
132
|
-
node_or_tags.each { |n| add_child_node_and_reparent_attrs
|
148
|
+
node_or_tags.each { |n| add_child_node_and_reparent_attrs(n) }
|
133
149
|
else
|
134
|
-
add_child_node_and_reparent_attrs
|
150
|
+
add_child_node_and_reparent_attrs(node_or_tags)
|
135
151
|
end
|
136
152
|
node_or_tags
|
137
153
|
end
|
@@ -144,9 +160,10 @@ module Nokogiri
|
|
144
160
|
#
|
145
161
|
# Also see related method +add_child+.
|
146
162
|
def prepend_child(node_or_tags)
|
147
|
-
if first = children.first
|
163
|
+
if (first = children.first)
|
148
164
|
# Mimic the error add_child would raise.
|
149
|
-
raise
|
165
|
+
raise "Document already has a root node" if document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
166
|
+
|
150
167
|
first.__send__(:add_sibling, :previous, node_or_tags)
|
151
168
|
else
|
152
169
|
add_child(node_or_tags)
|
@@ -172,7 +189,7 @@ module Nokogiri
|
|
172
189
|
#
|
173
190
|
# Also see related method +add_child+.
|
174
191
|
def <<(node_or_tags)
|
175
|
-
add_child
|
192
|
+
add_child(node_or_tags)
|
176
193
|
self
|
177
194
|
end
|
178
195
|
|
@@ -184,9 +201,10 @@ module Nokogiri
|
|
184
201
|
#
|
185
202
|
# Also see related method +before+.
|
186
203
|
def add_previous_sibling(node_or_tags)
|
187
|
-
raise ArgumentError
|
204
|
+
raise ArgumentError,
|
205
|
+
"A document may not have multiple root nodes." if parent&.document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
188
206
|
|
189
|
-
add_sibling
|
207
|
+
add_sibling(:previous, node_or_tags)
|
190
208
|
end
|
191
209
|
|
192
210
|
###
|
@@ -197,9 +215,10 @@ module Nokogiri
|
|
197
215
|
#
|
198
216
|
# Also see related method +after+.
|
199
217
|
def add_next_sibling(node_or_tags)
|
200
|
-
raise ArgumentError
|
218
|
+
raise ArgumentError,
|
219
|
+
"A document may not have multiple root nodes." if parent&.document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
201
220
|
|
202
|
-
add_sibling
|
221
|
+
add_sibling(:next, node_or_tags)
|
203
222
|
end
|
204
223
|
|
205
224
|
####
|
@@ -210,7 +229,7 @@ module Nokogiri
|
|
210
229
|
#
|
211
230
|
# Also see related method +add_previous_sibling+.
|
212
231
|
def before(node_or_tags)
|
213
|
-
add_previous_sibling
|
232
|
+
add_previous_sibling(node_or_tags)
|
214
233
|
self
|
215
234
|
end
|
216
235
|
|
@@ -222,7 +241,7 @@ module Nokogiri
|
|
222
241
|
#
|
223
242
|
# Also see related method +add_next_sibling+.
|
224
243
|
def after(node_or_tags)
|
225
|
-
add_next_sibling
|
244
|
+
add_next_sibling(node_or_tags)
|
226
245
|
self
|
227
246
|
end
|
228
247
|
|
@@ -230,30 +249,24 @@ module Nokogiri
|
|
230
249
|
# Set the inner html for this Node to +node_or_tags+
|
231
250
|
# +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
|
232
251
|
#
|
233
|
-
# Returns self.
|
234
|
-
#
|
235
252
|
# Also see related method +children=+
|
236
253
|
def inner_html=(node_or_tags)
|
237
254
|
self.children = node_or_tags
|
238
|
-
self
|
239
255
|
end
|
240
256
|
|
241
257
|
####
|
242
258
|
# Set the inner html for this Node +node_or_tags+
|
243
259
|
# +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
|
244
260
|
#
|
245
|
-
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
246
|
-
#
|
247
261
|
# Also see related method +inner_html=+
|
248
262
|
def children=(node_or_tags)
|
249
263
|
node_or_tags = coerce(node_or_tags)
|
250
264
|
children.unlink
|
251
265
|
if node_or_tags.is_a?(XML::NodeSet)
|
252
|
-
node_or_tags.each { |n| add_child_node_and_reparent_attrs
|
266
|
+
node_or_tags.each { |n| add_child_node_and_reparent_attrs(n) }
|
253
267
|
else
|
254
|
-
add_child_node_and_reparent_attrs
|
268
|
+
add_child_node_and_reparent_attrs(node_or_tags)
|
255
269
|
end
|
256
|
-
node_or_tags
|
257
270
|
end
|
258
271
|
|
259
272
|
####
|
@@ -271,19 +284,19 @@ module Nokogiri
|
|
271
284
|
# libxml is trying to find a parent node that is an element or document
|
272
285
|
# so I can't tell if this is bug in libxml or not. issue #775.
|
273
286
|
if text?
|
274
|
-
replacee = Nokogiri::XML::Node.new
|
275
|
-
add_previous_sibling_node
|
287
|
+
replacee = Nokogiri::XML::Node.new("dummy", document)
|
288
|
+
add_previous_sibling_node(replacee)
|
276
289
|
unlink
|
277
|
-
return replacee.replace
|
290
|
+
return replacee.replace(node_or_tags)
|
278
291
|
end
|
279
292
|
|
280
293
|
node_or_tags = parent.coerce(node_or_tags)
|
281
294
|
|
282
295
|
if node_or_tags.is_a?(XML::NodeSet)
|
283
|
-
node_or_tags.each { |n| add_previous_sibling
|
296
|
+
node_or_tags.each { |n| add_previous_sibling(n) }
|
284
297
|
unlink
|
285
298
|
else
|
286
|
-
replace_node
|
299
|
+
replace_node(node_or_tags)
|
287
300
|
end
|
288
301
|
node_or_tags
|
289
302
|
end
|
@@ -296,7 +309,7 @@ module Nokogiri
|
|
296
309
|
#
|
297
310
|
# Also see related method +replace+.
|
298
311
|
def swap(node_or_tags)
|
299
|
-
replace
|
312
|
+
replace(node_or_tags)
|
300
313
|
self
|
301
314
|
end
|
302
315
|
|
@@ -310,7 +323,6 @@ module Nokogiri
|
|
310
323
|
# Set the parent Node for this Node
|
311
324
|
def parent=(parent_node)
|
312
325
|
parent_node.add_child(self)
|
313
|
-
parent_node
|
314
326
|
end
|
315
327
|
|
316
328
|
###
|
@@ -339,7 +351,7 @@ module Nokogiri
|
|
339
351
|
raise ArgumentError, "namespace must be declared on the same document"
|
340
352
|
end
|
341
353
|
|
342
|
-
set_namespace
|
354
|
+
set_namespace(ns)
|
343
355
|
end
|
344
356
|
|
345
357
|
###
|
@@ -348,52 +360,159 @@ module Nokogiri
|
|
348
360
|
# passed to it, allowing more convenient modification of the parser options.
|
349
361
|
def do_xinclude(options = XML::ParseOptions::DEFAULT_XML)
|
350
362
|
options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
|
351
|
-
|
352
|
-
# give options to user
|
353
363
|
yield options if block_given?
|
354
364
|
|
355
365
|
# call c extension
|
356
366
|
process_xincludes(options.to_i)
|
357
367
|
end
|
358
368
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
369
|
+
alias_method :next, :next_sibling
|
370
|
+
alias_method :previous, :previous_sibling
|
371
|
+
alias_method :next=, :add_next_sibling
|
372
|
+
alias_method :previous=, :add_previous_sibling
|
373
|
+
alias_method :remove, :unlink
|
374
|
+
alias_method :name=, :node_name=
|
375
|
+
alias_method :add_namespace, :add_namespace_definition
|
366
376
|
|
367
|
-
#
|
377
|
+
# :section:
|
368
378
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
379
|
+
alias_method :inner_text, :content
|
380
|
+
alias_method :text, :content
|
381
|
+
alias_method :to_str, :content
|
382
|
+
alias_method :name, :node_name
|
383
|
+
alias_method :type, :node_type
|
384
|
+
alias_method :clone, :dup
|
385
|
+
alias_method :elements, :element_children
|
376
386
|
|
377
|
-
#
|
387
|
+
# :section: Working With Node Attributes
|
378
388
|
|
379
|
-
|
380
|
-
#
|
389
|
+
# :call-seq: [](name) → (String, nil)
|
390
|
+
#
|
391
|
+
# Fetch an attribute from this node.
|
392
|
+
#
|
393
|
+
# ⚠ Note that attributes with namespaces cannot be accessed with this method. To access
|
394
|
+
# namespaced attributes, use #attribute_with_ns.
|
395
|
+
#
|
396
|
+
# [Returns] (String, nil) value of the attribute +name+, or +nil+ if no matching attribute exists
|
397
|
+
#
|
398
|
+
# *Example*
|
399
|
+
#
|
400
|
+
# doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
|
401
|
+
# child = doc.at_css("child")
|
402
|
+
# child["size"] # => "large"
|
403
|
+
# child["class"] # => "big wide tall"
|
404
|
+
#
|
405
|
+
# *Example:* Namespaced attributes will not be returned.
|
406
|
+
#
|
407
|
+
# ⚠ Note namespaced attributes may be accessed with #attribute or #attribute_with_ns
|
408
|
+
#
|
409
|
+
# doc = Nokogiri::XML(<<~EOF)
|
410
|
+
# <root xmlns:width='http://example.com/widths'>
|
411
|
+
# <child width:size='broad'/>
|
412
|
+
# </root>
|
413
|
+
# EOF
|
414
|
+
# doc.at_css("child")["size"] # => nil
|
415
|
+
# doc.at_css("child").attribute("size").value # => "broad"
|
416
|
+
# doc.at_css("child").attribute_with_ns("size", "http://example.com/widths").value
|
417
|
+
# # => "broad"
|
418
|
+
#
|
381
419
|
def [](name)
|
382
420
|
get(name.to_s)
|
383
421
|
end
|
384
422
|
|
385
|
-
|
386
|
-
#
|
423
|
+
# :call-seq: []=(name, value) → value
|
424
|
+
#
|
425
|
+
# Update the attribute +name+ to +value+, or create the attribute if it does not exist.
|
426
|
+
#
|
427
|
+
# ⚠ Note that attributes with namespaces cannot be accessed with this method. To access
|
428
|
+
# namespaced attributes for update, use #attribute_with_ns. To add a namespaced attribute,
|
429
|
+
# see the example below.
|
430
|
+
#
|
431
|
+
# [Returns] +value+
|
432
|
+
#
|
433
|
+
# *Example*
|
434
|
+
#
|
435
|
+
# doc = Nokogiri::XML("<root><child/></root>")
|
436
|
+
# child = doc.at_css("child")
|
437
|
+
# child["size"] = "broad"
|
438
|
+
# child.to_html
|
439
|
+
# # => "<child size=\"broad\"></child>"
|
440
|
+
#
|
441
|
+
# *Example:* Add a namespaced attribute.
|
442
|
+
#
|
443
|
+
# doc = Nokogiri::XML(<<~EOF)
|
444
|
+
# <root xmlns:width='http://example.com/widths'>
|
445
|
+
# <child/>
|
446
|
+
# </root>
|
447
|
+
# EOF
|
448
|
+
# child = doc.at_css("child")
|
449
|
+
# child["size"] = "broad"
|
450
|
+
# ns = doc.root.namespace_definitions.find { |ns| ns.prefix == "width" }
|
451
|
+
# child.attribute("size").namespace = ns
|
452
|
+
# doc.to_html
|
453
|
+
# # => "<root xmlns:width=\"http://example.com/widths\">\n" +
|
454
|
+
# # " <child width:size=\"broad\"></child>\n" +
|
455
|
+
# # "</root>\n"
|
456
|
+
#
|
387
457
|
def []=(name, value)
|
388
|
-
set
|
458
|
+
set(name.to_s, value.to_s)
|
389
459
|
end
|
390
460
|
|
391
|
-
|
392
|
-
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
461
|
+
#
|
462
|
+
# :call-seq: attributes() → Hash<String ⇒ Nokogiri::XML::Attr>
|
463
|
+
#
|
464
|
+
# Fetch this node's attributes.
|
465
|
+
#
|
466
|
+
# ⚠ Because the keys do not include any namespace information for the attribute, in case of a
|
467
|
+
# simple name collision, not all attributes will be returned. In this case, you will need to
|
468
|
+
# use #attribute_nodes.
|
469
|
+
#
|
470
|
+
# [Returns]
|
471
|
+
# Hash containing attributes belonging to +self+. The hash keys are String attribute
|
472
|
+
# names (without the namespace), and the hash values are Nokogiri::XML::Attr.
|
473
|
+
#
|
474
|
+
# *Example* with no namespaces:
|
475
|
+
#
|
476
|
+
# doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
|
477
|
+
# doc.at_css("child").attributes
|
478
|
+
# # => {"size"=>#(Attr:0x550 { name = "size", value = "large" }),
|
479
|
+
# # "class"=>#(Attr:0x564 { name = "class", value = "big wide tall" })}
|
480
|
+
#
|
481
|
+
# *Example* with a namespace:
|
482
|
+
#
|
483
|
+
# doc = Nokogiri::XML("<root xmlns:desc='http://example.com/sizes'><child desc:size='large'/></root>")
|
484
|
+
# doc.at_css("child").attributes
|
485
|
+
# # => {"size"=>
|
486
|
+
# # #(Attr:0x550 {
|
487
|
+
# # name = "size",
|
488
|
+
# # namespace = #(Namespace:0x564 {
|
489
|
+
# # prefix = "desc",
|
490
|
+
# # href = "http://example.com/sizes"
|
491
|
+
# # }),
|
492
|
+
# # value = "large"
|
493
|
+
# # })}
|
494
|
+
#
|
495
|
+
# *Example* with an attribute name collision:
|
496
|
+
#
|
497
|
+
# ⚠ Note that only one of the attributes is returned in the Hash.
|
498
|
+
#
|
499
|
+
# doc = Nokogiri::XML(<<~EOF)
|
500
|
+
# <root xmlns:width='http://example.com/widths'
|
501
|
+
# xmlns:height='http://example.com/heights'>
|
502
|
+
# <child width:size='broad' height:size='tall'/>
|
503
|
+
# </root>
|
504
|
+
# EOF
|
505
|
+
# doc.at_css("child").attributes
|
506
|
+
# # => {"size"=>
|
507
|
+
# # #(Attr:0x550 {
|
508
|
+
# # name = "size",
|
509
|
+
# # namespace = #(Namespace:0x564 {
|
510
|
+
# # prefix = "height",
|
511
|
+
# # href = "http://example.com/heights"
|
512
|
+
# # }),
|
513
|
+
# # value = "tall"
|
514
|
+
# # })}
|
515
|
+
#
|
397
516
|
def attributes
|
398
517
|
attribute_nodes.each_with_object({}) do |node, hash|
|
399
518
|
hash[node.node_name] = node
|
@@ -409,7 +528,7 @@ module Nokogiri
|
|
409
528
|
###
|
410
529
|
# Does this Node's attributes include <value>
|
411
530
|
def value?(value)
|
412
|
-
values.include?
|
531
|
+
values.include?(value)
|
413
532
|
end
|
414
533
|
|
415
534
|
###
|
@@ -421,36 +540,36 @@ module Nokogiri
|
|
421
540
|
###
|
422
541
|
# Iterate over each attribute name and value pair for this Node.
|
423
542
|
def each
|
424
|
-
attribute_nodes.each
|
543
|
+
attribute_nodes.each do |node|
|
425
544
|
yield [node.node_name, node.value]
|
426
|
-
|
545
|
+
end
|
427
546
|
end
|
428
547
|
|
429
548
|
###
|
430
549
|
# Remove the attribute named +name+
|
431
550
|
def remove_attribute(name)
|
432
|
-
attr = attributes[name].remove if key?
|
551
|
+
attr = attributes[name].remove if key?(name)
|
433
552
|
clear_xpath_context if Nokogiri.jruby?
|
434
553
|
attr
|
435
554
|
end
|
436
555
|
|
437
|
-
#
|
556
|
+
#
|
557
|
+
# :call-seq: classes() → Array<String>
|
558
|
+
#
|
559
|
+
# Fetch CSS class names of a Node.
|
438
560
|
#
|
439
561
|
# This is a convenience function and is equivalent to:
|
562
|
+
#
|
440
563
|
# node.kwattr_values("class")
|
441
564
|
#
|
442
|
-
#
|
443
|
-
# @see #add_class
|
444
|
-
# @see #append_class
|
445
|
-
# @see #remove_class
|
565
|
+
# See related: #kwattr_values, #add_class, #append_class, #remove_class
|
446
566
|
#
|
447
|
-
#
|
567
|
+
# [Returns]
|
568
|
+
# The CSS classes (Array of String) present in the Node's "class" attribute. If the
|
569
|
+
# attribute is empty or non-existent, the return value is an empty array.
|
448
570
|
#
|
449
|
-
#
|
450
|
-
# the attribute is empty or non-existent, the return value is
|
451
|
-
# an empty array.
|
571
|
+
# *Example*
|
452
572
|
#
|
453
|
-
# @example
|
454
573
|
# node # => <div class="section title header"></div>
|
455
574
|
# node.classes # => ["section", "title", "header"]
|
456
575
|
#
|
@@ -458,42 +577,45 @@ module Nokogiri
|
|
458
577
|
kwattr_values("class")
|
459
578
|
end
|
460
579
|
|
461
|
-
#
|
462
|
-
#
|
463
|
-
#
|
464
|
-
#
|
465
|
-
#
|
580
|
+
#
|
581
|
+
# :call-seq: add_class(names) → self
|
582
|
+
#
|
583
|
+
# Ensure HTML CSS classes are present on +self+. Any CSS classes in +names+ that already exist
|
584
|
+
# in the "class" attribute are _not_ added. Note that any existing duplicates in the
|
585
|
+
# "class" attribute are not removed. Compare with #append_class.
|
466
586
|
#
|
467
587
|
# This is a convenience function and is equivalent to:
|
588
|
+
#
|
468
589
|
# node.kwattr_add("class", names)
|
469
590
|
#
|
470
|
-
#
|
471
|
-
# @see #classes
|
472
|
-
# @see #append_class
|
473
|
-
# @see #remove_class
|
591
|
+
# See related: #kwattr_add, #classes, #append_class, #remove_class
|
474
592
|
#
|
475
|
-
#
|
593
|
+
# [Parameters]
|
594
|
+
# - +names+ (String, Array<String>)
|
476
595
|
#
|
477
|
-
# CSS class names to be added to the Node's
|
478
|
-
#
|
479
|
-
#
|
480
|
-
#
|
481
|
-
# be added. If no +class+ attribute exists, one is created.
|
596
|
+
# CSS class names to be added to the Node's "class" attribute. May be a string containing
|
597
|
+
# whitespace-delimited names, or an Array of String names. Any class names already present
|
598
|
+
# will not be added. Any class names not present will be added. If no "class" attribute
|
599
|
+
# exists, one is created.
|
482
600
|
#
|
483
|
-
#
|
601
|
+
# [Returns] +self+ (Node) for ease of chaining method calls.
|
602
|
+
#
|
603
|
+
# *Example:* Ensure that the node has CSS class "section"
|
484
604
|
#
|
485
|
-
# @example Ensure that a +Node+ has CSS class "section"
|
486
605
|
# node # => <div></div>
|
487
606
|
# node.add_class("section") # => <div class="section"></div>
|
488
607
|
# node.add_class("section") # => <div class="section"></div> # duplicate not added
|
489
608
|
#
|
490
|
-
#
|
609
|
+
# *Example:* Ensure that the node has CSS classes "section" and "header", via a String argument
|
610
|
+
#
|
611
|
+
# Note that the CSS class "section" is not added because it is already present.
|
612
|
+
# Note also that the pre-existing duplicate CSS class "section" is not removed.
|
613
|
+
#
|
491
614
|
# node # => <div class="section section"></div>
|
492
615
|
# node.add_class("section header") # => <div class="section section header"></div>
|
493
|
-
# # Note that the CSS class "section" is not added because it is already present.
|
494
|
-
# # Note also that the pre-existing duplicate CSS class "section" is not removed.
|
495
616
|
#
|
496
|
-
#
|
617
|
+
# *Example:* Ensure that the node has CSS classes "section" and "header", via an Array argument
|
618
|
+
#
|
497
619
|
# node # => <div></div>
|
498
620
|
# node.add_class(["section", "header"]) # => <div class="section header"></div>
|
499
621
|
#
|
@@ -501,39 +623,42 @@ module Nokogiri
|
|
501
623
|
kwattr_add("class", names)
|
502
624
|
end
|
503
625
|
|
504
|
-
#
|
505
|
-
#
|
626
|
+
#
|
627
|
+
# :call-seq: append_class(names) → self
|
628
|
+
#
|
629
|
+
# Add HTML CSS classes to +self+, regardless of duplication. Compare with #add_class.
|
506
630
|
#
|
507
631
|
# This is a convenience function and is equivalent to:
|
632
|
+
#
|
508
633
|
# node.kwattr_append("class", names)
|
509
634
|
#
|
510
|
-
#
|
511
|
-
#
|
512
|
-
#
|
513
|
-
#
|
635
|
+
# See related: #kwattr_append, #classes, #add_class, #remove_class
|
636
|
+
#
|
637
|
+
# [Parameters]
|
638
|
+
# - +names+ (String, Array<String>)
|
514
639
|
#
|
515
|
-
#
|
640
|
+
# CSS class names to be appended to the Node's "class" attribute. May be a string containing
|
641
|
+
# whitespace-delimited names, or an Array of String names. All class names passed in will be
|
642
|
+
# appended to the "class" attribute even if they are already present in the attribute
|
643
|
+
# value. If no "class" attribute exists, one is created.
|
516
644
|
#
|
517
|
-
#
|
518
|
-
# attribute. May be a string containing whitespace-delimited
|
519
|
-
# names, or an Array of String names. All class names passed
|
520
|
-
# in will be appended to the +class+ attribute even if they
|
521
|
-
# are already present in the attribute value. If no +class+
|
522
|
-
# attribute exists, one is created.
|
645
|
+
# [Returns] +self+ (Node) for ease of chaining method calls.
|
523
646
|
#
|
524
|
-
#
|
647
|
+
# *Example:* Append "section" to the node's CSS "class" attribute
|
525
648
|
#
|
526
|
-
# @example Append "section" to a +Node+'s CSS +class+ attriubute
|
527
649
|
# node # => <div></div>
|
528
650
|
# node.append_class("section") # => <div class="section"></div>
|
529
651
|
# node.append_class("section") # => <div class="section section"></div> # duplicate added!
|
530
652
|
#
|
531
|
-
#
|
653
|
+
# *Example:* Append "section" and "header" to the noded's CSS "class" attribute, via a String argument
|
654
|
+
#
|
655
|
+
# Note that the CSS class "section" is appended even though it is already present
|
656
|
+
#
|
532
657
|
# node # => <div class="section section"></div>
|
533
658
|
# node.append_class("section header") # => <div class="section section section header"></div>
|
534
|
-
# # Note that the CSS class "section" is appended even though it is already present.
|
535
659
|
#
|
536
|
-
#
|
660
|
+
# *Example:* Append "section" and "header" to the node's CSS "class" attribute, via an Array argument
|
661
|
+
#
|
537
662
|
# node # => <div></div>
|
538
663
|
# node.append_class(["section", "header"]) # => <div class="section header"></div>
|
539
664
|
# node.append_class(["section", "header"]) # => <div class="section header section header"></div>
|
@@ -542,118 +667,135 @@ module Nokogiri
|
|
542
667
|
kwattr_append("class", names)
|
543
668
|
end
|
544
669
|
|
545
|
-
#
|
546
|
-
#
|
547
|
-
#
|
670
|
+
# :call-seq:
|
671
|
+
# remove_class(css_classes) → self
|
672
|
+
#
|
673
|
+
# Remove HTML CSS classes from this node. Any CSS class names in +css_classes+ that exist in
|
674
|
+
# this node's "class" attribute are removed, including any multiple entries.
|
548
675
|
#
|
549
|
-
# If no CSS classes remain after this operation, or if +
|
550
|
-
#
|
676
|
+
# If no CSS classes remain after this operation, or if +css_classes+ is +nil+, the "class"
|
677
|
+
# attribute is deleted from the node.
|
551
678
|
#
|
552
679
|
# This is a convenience function and is equivalent to:
|
553
|
-
# node.kwattr_remove("class", names)
|
554
680
|
#
|
555
|
-
#
|
556
|
-
# @see #classes
|
557
|
-
# @see #add_class
|
558
|
-
# @see #append_class
|
681
|
+
# node.kwattr_remove("class", css_classes)
|
559
682
|
#
|
560
|
-
#
|
683
|
+
# Also see #kwattr_remove, #classes, #add_class, #append_class
|
561
684
|
#
|
562
|
-
#
|
563
|
-
#
|
564
|
-
# String names. Any class names already present will be removed. If no
|
565
|
-
# CSS classes remain, the +class+ attribute is deleted.
|
685
|
+
# [Parameters]
|
686
|
+
# - +css_classes+ (String, Array<String>)
|
566
687
|
#
|
567
|
-
#
|
688
|
+
# CSS class names to be removed from the Node's
|
689
|
+
# "class" attribute. May be a string containing whitespace-delimited names, or an Array of
|
690
|
+
# String names. Any class names already present will be removed. If no CSS classes remain,
|
691
|
+
# the "class" attribute is deleted.
|
568
692
|
#
|
569
|
-
#
|
570
|
-
#
|
693
|
+
# [Returns] +self+ (Nokogiri::XML::Node) for ease of chaining method calls.
|
694
|
+
#
|
695
|
+
# *Example*: Deleting a CSS class
|
696
|
+
#
|
697
|
+
# Note that all instances of the class "section" are removed from the "class" attribute.
|
698
|
+
#
|
699
|
+
# node # => <div class="section header section"></div>
|
571
700
|
# node.remove_class("section") # => <div class="header"></div>
|
572
|
-
#
|
701
|
+
#
|
702
|
+
# *Example*: Deleting the only remaining CSS class
|
703
|
+
#
|
704
|
+
# Note that the attribute is removed once there are no remaining classes.
|
705
|
+
#
|
706
|
+
# node # => <div class="section"></div>
|
707
|
+
# node.remove_class("section") # => <div></div>
|
708
|
+
#
|
709
|
+
# *Example*: Deleting multiple CSS classes
|
710
|
+
#
|
711
|
+
# Note that the "class" attribute is deleted once it's empty.
|
712
|
+
#
|
713
|
+
# node # => <div class="section header float"></div>
|
714
|
+
# node.remove_class(["section", "float"]) # => <div class="header"></div>
|
573
715
|
#
|
574
716
|
def remove_class(names = nil)
|
575
717
|
kwattr_remove("class", names)
|
576
718
|
end
|
577
719
|
|
578
|
-
#
|
720
|
+
# :call-seq:
|
721
|
+
# kwattr_values(attribute_name) → Array<String>
|
722
|
+
#
|
723
|
+
# Fetch values from a keyword attribute of a Node.
|
579
724
|
#
|
580
|
-
# A "keyword attribute" is a node attribute that contains a set
|
581
|
-
#
|
582
|
-
#
|
583
|
-
#
|
584
|
-
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
725
|
+
# A "keyword attribute" is a node attribute that contains a set of space-delimited
|
726
|
+
# values. Perhaps the most familiar example of this is the HTML "class" attribute used to
|
727
|
+
# contain CSS classes. But other keyword attributes exist, for instance
|
728
|
+
# {the "rel" attribute}[https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel].
|
585
729
|
#
|
586
|
-
#
|
587
|
-
# @see #kwattr_add
|
588
|
-
# @see #kwattr_append
|
589
|
-
# @see #kwattr_remove
|
730
|
+
# See also #classes, #kwattr_add, #kwattr_append, #kwattr_remove
|
590
731
|
#
|
591
|
-
#
|
732
|
+
# [Parameters]
|
733
|
+
# - +attribute_name+ (String) The name of the keyword attribute to be inspected.
|
592
734
|
#
|
593
|
-
#
|
735
|
+
# [Returns]
|
736
|
+
# (Array<String>) The values present in the Node's +attribute_name+ attribute. If the
|
737
|
+
# attribute is empty or non-existent, the return value is an empty array.
|
594
738
|
#
|
595
|
-
#
|
596
|
-
# attribute. If the attribute is empty or non-existent, the
|
597
|
-
# return value is an empty array.
|
739
|
+
# *Example:*
|
598
740
|
#
|
599
|
-
# @example
|
600
741
|
# node # => <a rel="nofollow noopener external">link</a>
|
601
742
|
# node.kwattr_values("rel") # => ["nofollow", "noopener", "external"]
|
602
743
|
#
|
603
|
-
#
|
604
|
-
#
|
744
|
+
# Since v1.11.0
|
605
745
|
def kwattr_values(attribute_name)
|
606
746
|
keywordify(get_attribute(attribute_name) || [])
|
607
747
|
end
|
608
748
|
|
749
|
+
# :call-seq:
|
750
|
+
# kwattr_add(attribute_name, keywords) → self
|
751
|
+
#
|
609
752
|
# Ensure that values are present in a keyword attribute.
|
610
753
|
#
|
611
|
-
# Any values in +keywords+ that already exist in the
|
612
|
-
#
|
613
|
-
#
|
614
|
-
# with {#kwattr_append}.
|
754
|
+
# Any values in +keywords+ that already exist in the Node's attribute values are _not_
|
755
|
+
# added. Note that any existing duplicates in the attribute values are not removed. Compare
|
756
|
+
# with #kwattr_append.
|
615
757
|
#
|
616
|
-
# A "keyword attribute" is a node attribute that contains a set
|
617
|
-
#
|
618
|
-
#
|
619
|
-
#
|
620
|
-
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
758
|
+
# A "keyword attribute" is a node attribute that contains a set of space-delimited
|
759
|
+
# values. Perhaps the most familiar example of this is the HTML "class" attribute used to
|
760
|
+
# contain CSS classes. But other keyword attributes exist, for instance
|
761
|
+
# {the "rel" attribute}[https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel].
|
621
762
|
#
|
622
|
-
#
|
623
|
-
# @see #kwattr_values
|
624
|
-
# @see #kwattr_append
|
625
|
-
# @see #kwattr_remove
|
763
|
+
# See also #add_class, #kwattr_values, #kwattr_append, #kwattr_remove
|
626
764
|
#
|
627
|
-
#
|
765
|
+
# [Parameters]
|
766
|
+
# - +attribute_name+ (String) The name of the keyword attribute to be modified.
|
767
|
+
# - +keywords+ (String, Array<String>)
|
768
|
+
# Keywords to be added to the attribute named +attribute_name+. May be a string containing
|
769
|
+
# whitespace-delimited values, or an Array of String values. Any values already present will
|
770
|
+
# not be added. Any values not present will be added. If the named attribute does not exist,
|
771
|
+
# it is created.
|
628
772
|
#
|
629
|
-
#
|
773
|
+
# [Returns] +self+ (Nokogiri::XML::Node) for ease of chaining method calls.
|
630
774
|
#
|
631
|
-
#
|
632
|
-
# +attribute_name+. May be a string containing
|
633
|
-
# whitespace-delimited values, or an Array of String
|
634
|
-
# values. Any values already present will not be added. Any
|
635
|
-
# values not present will be added. If the named attribute
|
636
|
-
# does not exist, it is created.
|
775
|
+
# *Example:* Ensure that a +Node+ has "nofollow" in its +rel+ attribute.
|
637
776
|
#
|
638
|
-
#
|
777
|
+
# Note that duplicates are not added.
|
639
778
|
#
|
640
|
-
# @example Ensure that a +Node+ has "nofollow" in its +rel+ attribute.
|
641
779
|
# node # => <a></a>
|
642
780
|
# node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a>
|
643
|
-
# node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a>
|
781
|
+
# node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a>
|
782
|
+
#
|
783
|
+
# *Example:* Ensure that a +Node+ has "nofollow" and "noreferrer" in its +rel+ attribute, via a
|
784
|
+
# String argument.
|
785
|
+
#
|
786
|
+
# Note that "nofollow" is not added because it is already present. Note also that the
|
787
|
+
# pre-existing duplicate "nofollow" is not removed.
|
644
788
|
#
|
645
|
-
# @example Ensure that a +Node+ has "nofollow" and "noreferrer" in its +rel+ attribute, via a String argument.
|
646
789
|
# node # => <a rel="nofollow nofollow"></a>
|
647
790
|
# node.kwattr_add("rel", "nofollow noreferrer") # => <a rel="nofollow nofollow noreferrer"></a>
|
648
|
-
# # Note that "nofollow" is not added because it is already present.
|
649
|
-
# # Note also that the pre-existing duplicate "nofollow" is not removed.
|
650
791
|
#
|
651
|
-
#
|
792
|
+
# *Example:* Ensure that a +Node+ has "nofollow" and "noreferrer" in its +rel+ attribute, via
|
793
|
+
# an Array argument.
|
794
|
+
#
|
652
795
|
# node # => <a></a>
|
653
796
|
# node.kwattr_add("rel", ["nofollow", "noreferrer"]) # => <a rel="nofollow noreferrer"></a>
|
654
797
|
#
|
655
|
-
#
|
656
|
-
#
|
798
|
+
# Since v1.11.0
|
657
799
|
def kwattr_add(attribute_name, keywords)
|
658
800
|
keywords = keywordify(keywords)
|
659
801
|
current_kws = kwattr_values(attribute_name)
|
@@ -662,50 +804,51 @@ module Nokogiri
|
|
662
804
|
self
|
663
805
|
end
|
664
806
|
|
665
|
-
#
|
666
|
-
#
|
807
|
+
# :call-seq:
|
808
|
+
# kwattr_append(attribute_name, keywords) → self
|
667
809
|
#
|
668
|
-
#
|
669
|
-
#
|
670
|
-
# of this is the HTML +class+ attribute used to contain CSS
|
671
|
-
# classes. But other keyword attributes exist, for instance
|
672
|
-
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
810
|
+
# Add keywords to a Node's keyword attribute, regardless of duplication. Compare with
|
811
|
+
# #kwattr_add.
|
673
812
|
#
|
674
|
-
#
|
675
|
-
#
|
676
|
-
#
|
677
|
-
#
|
813
|
+
# A "keyword attribute" is a node attribute that contains a set of space-delimited
|
814
|
+
# values. Perhaps the most familiar example of this is the HTML "class" attribute used to
|
815
|
+
# contain CSS classes. But other keyword attributes exist, for instance
|
816
|
+
# {the "rel" attribute}[https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel].
|
678
817
|
#
|
679
|
-
#
|
818
|
+
# See also #append_class, #kwattr_values, #kwattr_add, #kwattr_remove
|
680
819
|
#
|
681
|
-
#
|
820
|
+
# [Parameters]
|
821
|
+
# - +attribute_name+ (String) The name of the keyword attribute to be modified.
|
822
|
+
# - +keywords+ (String, Array<String>)
|
823
|
+
# Keywords to be added to the attribute named +attribute_name+. May be a string containing
|
824
|
+
# whitespace-delimited values, or an Array of String values. All values passed in will be
|
825
|
+
# appended to the named attribute even if they are already present in the attribute. If the
|
826
|
+
# named attribute does not exist, it is created.
|
682
827
|
#
|
683
|
-
#
|
684
|
-
# +attribute_name+. May be a string containing
|
685
|
-
# whitespace-delimited values, or an Array of String
|
686
|
-
# values. All values passed in will be appended to the named
|
687
|
-
# attribute even if they are already present in the
|
688
|
-
# attribute. If the named attribute does not exist, it is
|
689
|
-
# created.
|
828
|
+
# [Returns] +self+ (Node) for ease of chaining method calls.
|
690
829
|
#
|
691
|
-
#
|
830
|
+
# *Example:* Append "nofollow" to the +rel+ attribute.
|
831
|
+
#
|
832
|
+
# Note that duplicates are added.
|
692
833
|
#
|
693
|
-
# @example Append "nofollow" to the +rel+ attribute.
|
694
834
|
# node # => <a></a>
|
695
835
|
# node.kwattr_append("rel", "nofollow") # => <a rel="nofollow"></a>
|
696
|
-
# node.kwattr_append("rel", "nofollow") # => <a rel="nofollow nofollow"></a>
|
836
|
+
# node.kwattr_append("rel", "nofollow") # => <a rel="nofollow nofollow"></a>
|
837
|
+
#
|
838
|
+
# *Example:* Append "nofollow" and "noreferrer" to the +rel+ attribute, via a String argument.
|
839
|
+
#
|
840
|
+
# Note that "nofollow" is appended even though it is already present.
|
697
841
|
#
|
698
|
-
# @example Append "nofollow" and "noreferrer" to the +rel+ attribute, via a String argument.
|
699
842
|
# node # => <a rel="nofollow"></a>
|
700
843
|
# node.kwattr_append("rel", "nofollow noreferrer") # => <a rel="nofollow nofollow noreferrer"></a>
|
701
|
-
# # Note that "nofollow" is appended even though it is already present.
|
702
844
|
#
|
703
|
-
#
|
845
|
+
#
|
846
|
+
# *Example:* Append "nofollow" and "noreferrer" to the +rel+ attribute, via an Array argument.
|
847
|
+
#
|
704
848
|
# node # => <a></a>
|
705
849
|
# node.kwattr_append("rel", ["nofollow", "noreferrer"]) # => <a rel="nofollow noreferrer"></a>
|
706
850
|
#
|
707
|
-
#
|
708
|
-
#
|
851
|
+
# Since v1.11.0
|
709
852
|
def kwattr_append(attribute_name, keywords)
|
710
853
|
keywords = keywordify(keywords)
|
711
854
|
current_kws = kwattr_values(attribute_name)
|
@@ -714,44 +857,41 @@ module Nokogiri
|
|
714
857
|
self
|
715
858
|
end
|
716
859
|
|
717
|
-
#
|
718
|
-
# keywords
|
719
|
-
# including any multiple entries.
|
860
|
+
# :call-seq:
|
861
|
+
# kwattr_remove(attribute_name, keywords) → self
|
720
862
|
#
|
721
|
-
#
|
722
|
-
#
|
863
|
+
# Remove keywords from a keyword attribute. Any matching keywords that exist in the named
|
864
|
+
# attribute are removed, including any multiple entries.
|
723
865
|
#
|
724
|
-
#
|
725
|
-
#
|
726
|
-
# of this is the HTML +class+ attribute used to contain CSS
|
727
|
-
# classes. But other keyword attributes exist, for instance
|
728
|
-
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
866
|
+
# If no keywords remain after this operation, or if +keywords+ is +nil+, the attribute is
|
867
|
+
# deleted from the node.
|
729
868
|
#
|
730
|
-
#
|
731
|
-
#
|
732
|
-
#
|
733
|
-
#
|
869
|
+
# A "keyword attribute" is a node attribute that contains a set of space-delimited
|
870
|
+
# values. Perhaps the most familiar example of this is the HTML "class" attribute used to
|
871
|
+
# contain CSS classes. But other keyword attributes exist, for instance
|
872
|
+
# {the "rel" attribute}[https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel].
|
734
873
|
#
|
735
|
-
#
|
874
|
+
# See also #remove_class, #kwattr_values, #kwattr_add, #kwattr_append
|
736
875
|
#
|
737
|
-
#
|
876
|
+
# [Parameters]
|
877
|
+
# - +attribute_name+ (String) The name of the keyword attribute to be modified.
|
878
|
+
# - +keywords+ (String, Array<String>)
|
879
|
+
# Keywords to be removed from the attribute named +attribute_name+. May be a string
|
880
|
+
# containing whitespace-delimited values, or an Array of String values. Any keywords present
|
881
|
+
# in the named attribute will be removed. If no keywords remain, or if +keywords+ is nil,
|
882
|
+
# the attribute is deleted.
|
738
883
|
#
|
739
|
-
#
|
740
|
-
# +attribute_name+. May be a string containing
|
741
|
-
# whitespace-delimited values, or an Array of String
|
742
|
-
# values. Any keywords present in the named attribute will be
|
743
|
-
# removed. If no keywords remain, or if +keywords+ is nil, the
|
744
|
-
# attribute is deleted.
|
884
|
+
# [Returns] +self+ (Node) for ease of chaining method calls.
|
745
885
|
#
|
746
|
-
#
|
886
|
+
# *Example:*
|
887
|
+
#
|
888
|
+
# Note that the +rel+ attribute is deleted when empty.
|
747
889
|
#
|
748
|
-
# @example
|
749
890
|
# node # => <a rel="nofollow noreferrer">link</a>
|
750
891
|
# node.kwattr_remove("rel", "nofollow") # => <a rel="noreferrer">link</a>
|
751
|
-
# node.kwattr_remove("rel", "noreferrer") # => <a>link</a>
|
752
|
-
#
|
753
|
-
# @since v1.11.0
|
892
|
+
# node.kwattr_remove("rel", "noreferrer") # => <a>link</a>
|
754
893
|
#
|
894
|
+
# Since v1.11.0
|
755
895
|
def kwattr_remove(attribute_name, keywords)
|
756
896
|
if keywords.nil?
|
757
897
|
remove_attribute(attribute_name)
|
@@ -769,13 +909,13 @@ module Nokogiri
|
|
769
909
|
self
|
770
910
|
end
|
771
911
|
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
912
|
+
alias_method :delete, :remove_attribute
|
913
|
+
alias_method :get_attribute, :[]
|
914
|
+
alias_method :attr, :[]
|
915
|
+
alias_method :set_attribute, :[]=
|
916
|
+
alias_method :has_attribute?, :key?
|
777
917
|
|
778
|
-
#
|
918
|
+
# :section:
|
779
919
|
|
780
920
|
###
|
781
921
|
# Returns true if this Node matches +selector+
|
@@ -787,8 +927,7 @@ module Nokogiri
|
|
787
927
|
# Create a DocumentFragment containing +tags+ that is relative to _this_
|
788
928
|
# context node.
|
789
929
|
def fragment(tags)
|
790
|
-
|
791
|
-
type::DocumentFragment.new(document, tags, self)
|
930
|
+
document.related_class("DocumentFragment").new(document, tags, self)
|
792
931
|
end
|
793
932
|
|
794
933
|
###
|
@@ -806,19 +945,18 @@ module Nokogiri
|
|
806
945
|
end
|
807
946
|
|
808
947
|
options ||= (document.html? ? ParseOptions::DEFAULT_HTML : ParseOptions::DEFAULT_XML)
|
809
|
-
if Integer === options
|
810
|
-
options = Nokogiri::XML::ParseOptions.new(options)
|
811
|
-
end
|
812
|
-
# Give the options to the user
|
948
|
+
options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
|
813
949
|
yield options if block_given?
|
814
950
|
|
815
|
-
contents = string_or_io.respond_to?(:read)
|
816
|
-
string_or_io.read
|
951
|
+
contents = if string_or_io.respond_to?(:read)
|
952
|
+
string_or_io.read
|
953
|
+
else
|
817
954
|
string_or_io
|
955
|
+
end
|
818
956
|
|
819
957
|
return Nokogiri::XML::NodeSet.new(document) if contents.empty?
|
820
958
|
|
821
|
-
# libxml2 does not obey the
|
959
|
+
# libxml2 does not obey the +recover+ option after encountering errors during +in_context+
|
822
960
|
# parsing, and so this horrible hack is here to try to emulate recovery behavior.
|
823
961
|
#
|
824
962
|
# Unfortunately, this means we're no longer parsing "in context" and so namespaces that
|
@@ -828,16 +966,16 @@ module Nokogiri
|
|
828
966
|
#
|
829
967
|
# I think preferable behavior would be to either:
|
830
968
|
#
|
831
|
-
# a. add an error noting that we "fell back" and pointing the user to turning off the
|
969
|
+
# a. add an error noting that we "fell back" and pointing the user to turning off the +recover+ option
|
832
970
|
# b. don't recover, but raise a sensible exception
|
833
971
|
#
|
834
972
|
# For context and background: https://github.com/sparklemotion/nokogiri/issues/313
|
835
973
|
# FIXME bug report: https://github.com/sparklemotion/nokogiri/issues/2092
|
836
974
|
error_count = document.errors.length
|
837
975
|
node_set = in_context(contents, options.to_i)
|
838
|
-
if
|
976
|
+
if node_set.empty? && (document.errors.length > error_count)
|
839
977
|
if options.recover?
|
840
|
-
fragment =
|
978
|
+
fragment = document.related_class("DocumentFragment").parse(contents)
|
841
979
|
node_set = fragment.children
|
842
980
|
else
|
843
981
|
raise document.errors[error_count]
|
@@ -846,20 +984,42 @@ module Nokogiri
|
|
846
984
|
node_set
|
847
985
|
end
|
848
986
|
|
849
|
-
|
850
|
-
#
|
851
|
-
#
|
852
|
-
#
|
853
|
-
#
|
854
|
-
#
|
855
|
-
#
|
856
|
-
#
|
857
|
-
#
|
858
|
-
#
|
859
|
-
#
|
860
|
-
#
|
861
|
-
#
|
862
|
-
#
|
987
|
+
# :call-seq:
|
988
|
+
# namespaces() → Hash<String(Namespace#prefix) ⇒ String(Namespace#href)>
|
989
|
+
#
|
990
|
+
# Fetch all the namespaces on this node and its ancestors.
|
991
|
+
#
|
992
|
+
# Note that the keys in this hash XML attributes that would be used to define this namespace,
|
993
|
+
# such as "xmlns:prefix", not just the prefix.
|
994
|
+
#
|
995
|
+
# The default namespace for this node will be included with key "xmlns".
|
996
|
+
#
|
997
|
+
# See also #namespace_scopes
|
998
|
+
#
|
999
|
+
# [Returns]
|
1000
|
+
# Hash containing all the namespaces on this node and its ancestors. The hash keys are the
|
1001
|
+
# namespace prefix, and the hash value for each key is the namespace URI.
|
1002
|
+
#
|
1003
|
+
# *Example:*
|
1004
|
+
#
|
1005
|
+
# doc = Nokogiri::XML(<<~EOF)
|
1006
|
+
# <root xmlns="http://example.com/root" xmlns:in_scope="http://example.com/in_scope">
|
1007
|
+
# <first/>
|
1008
|
+
# <second xmlns="http://example.com/child"/>
|
1009
|
+
# <third xmlns:foo="http://example.com/foo"/>
|
1010
|
+
# </root>
|
1011
|
+
# EOF
|
1012
|
+
# doc.at_xpath("//root:first", "root" => "http://example.com/root").namespaces
|
1013
|
+
# # => {"xmlns"=>"http://example.com/root",
|
1014
|
+
# # "xmlns:in_scope"=>"http://example.com/in_scope"}
|
1015
|
+
# doc.at_xpath("//child:second", "child" => "http://example.com/child").namespaces
|
1016
|
+
# # => {"xmlns"=>"http://example.com/child",
|
1017
|
+
# # "xmlns:in_scope"=>"http://example.com/in_scope"}
|
1018
|
+
# doc.at_xpath("//root:third", "root" => "http://example.com/root").namespaces
|
1019
|
+
# # => {"xmlns:foo"=>"http://example.com/foo",
|
1020
|
+
# # "xmlns"=>"http://example.com/root",
|
1021
|
+
# # "xmlns:in_scope"=>"http://example.com/in_scope"}
|
1022
|
+
#
|
863
1023
|
def namespaces
|
864
1024
|
namespace_scopes.each_with_object({}) do |ns, hash|
|
865
1025
|
prefix = ns.prefix
|
@@ -883,14 +1043,14 @@ module Nokogiri
|
|
883
1043
|
type == DOCUMENT_NODE
|
884
1044
|
end
|
885
1045
|
|
886
|
-
# Returns true if this is an
|
1046
|
+
# Returns true if this is an HTML4::Document or HTML5::Document node
|
887
1047
|
def html?
|
888
1048
|
type == HTML_DOCUMENT_NODE
|
889
1049
|
end
|
890
1050
|
|
891
1051
|
# Returns true if this is a Document
|
892
1052
|
def document?
|
893
|
-
is_a?
|
1053
|
+
is_a?(XML::Document)
|
894
1054
|
end
|
895
1055
|
|
896
1056
|
# Returns true if this is a ProcessingInstruction node
|
@@ -909,11 +1069,12 @@ module Nokogiri
|
|
909
1069
|
end
|
910
1070
|
|
911
1071
|
###
|
912
|
-
# Fetch the Nokogiri::
|
1072
|
+
# Fetch the Nokogiri::HTML4::ElementDescription for this node. Returns
|
913
1073
|
# nil on XML documents and on unknown tags.
|
914
1074
|
def description
|
915
1075
|
return nil if document.xml?
|
916
|
-
|
1076
|
+
|
1077
|
+
Nokogiri::HTML4::ElementDescription[name]
|
917
1078
|
end
|
918
1079
|
|
919
1080
|
###
|
@@ -928,7 +1089,7 @@ module Nokogiri
|
|
928
1089
|
type == ELEMENT_NODE
|
929
1090
|
end
|
930
1091
|
|
931
|
-
|
1092
|
+
alias_method :elem?, :element?
|
932
1093
|
|
933
1094
|
###
|
934
1095
|
# Turn this node in to a string. If the document is HTML, this method
|
@@ -944,9 +1105,9 @@ module Nokogiri
|
|
944
1105
|
|
945
1106
|
# Get the path to this node as a CSS expression
|
946
1107
|
def css_path
|
947
|
-
path.split(
|
948
|
-
part.
|
949
|
-
|
1108
|
+
path.split(%r{/}).map do |part|
|
1109
|
+
part.empty? ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
|
1110
|
+
end.compact.join(" > ")
|
950
1111
|
end
|
951
1112
|
|
952
1113
|
###
|
@@ -959,7 +1120,8 @@ module Nokogiri
|
|
959
1120
|
parents = [parent]
|
960
1121
|
|
961
1122
|
while parents.last.respond_to?(:parent)
|
962
|
-
break unless ctx_parent = parents.last.parent
|
1123
|
+
break unless (ctx_parent = parents.last.parent)
|
1124
|
+
|
963
1125
|
parents << ctx_parent
|
964
1126
|
end
|
965
1127
|
|
@@ -968,16 +1130,16 @@ module Nokogiri
|
|
968
1130
|
root = parents.last
|
969
1131
|
search_results = root.search(selector)
|
970
1132
|
|
971
|
-
NodeSet.new(document, parents.find_all
|
1133
|
+
NodeSet.new(document, parents.find_all do |parent|
|
972
1134
|
search_results.include?(parent)
|
973
|
-
|
1135
|
+
end)
|
974
1136
|
end
|
975
1137
|
|
976
1138
|
####
|
977
1139
|
# Yields self and all children to +block+ recursively.
|
978
1140
|
def traverse(&block)
|
979
1141
|
children.each { |j| j.traverse(&block) }
|
980
|
-
|
1142
|
+
yield(self)
|
981
1143
|
end
|
982
1144
|
|
983
1145
|
###
|
@@ -991,6 +1153,7 @@ module Nokogiri
|
|
991
1153
|
def ==(other)
|
992
1154
|
return false unless other
|
993
1155
|
return false unless other.respond_to?(:pointer_id)
|
1156
|
+
|
994
1157
|
pointer_id == other.pointer_id
|
995
1158
|
end
|
996
1159
|
|
@@ -1000,14 +1163,16 @@ module Nokogiri
|
|
1000
1163
|
def <=>(other)
|
1001
1164
|
return nil unless other.is_a?(Nokogiri::XML::Node)
|
1002
1165
|
return nil unless document == other.document
|
1003
|
-
|
1166
|
+
|
1167
|
+
compare(other)
|
1004
1168
|
end
|
1005
1169
|
|
1006
|
-
#
|
1170
|
+
# :section: Serialization and Generating Output
|
1007
1171
|
|
1008
1172
|
###
|
1009
|
-
# Serialize Node using +options+.
|
1010
|
-
#
|
1173
|
+
# Serialize Node using +options+. Save options can also be set using a block.
|
1174
|
+
#
|
1175
|
+
# See also Nokogiri::XML::Node::SaveOptions and Node@Serialization+and+Generating+Output.
|
1011
1176
|
#
|
1012
1177
|
# These two statements are equivalent:
|
1013
1178
|
#
|
@@ -1020,18 +1185,22 @@ module Nokogiri
|
|
1020
1185
|
# end
|
1021
1186
|
#
|
1022
1187
|
def serialize(*args, &block)
|
1023
|
-
options = args.first.is_a?(Hash)
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1188
|
+
options = if args.first.is_a?(Hash)
|
1189
|
+
args.shift
|
1190
|
+
else
|
1191
|
+
{
|
1192
|
+
encoding: args[0],
|
1193
|
+
save_with: args[1],
|
1194
|
+
}
|
1195
|
+
end
|
1027
1196
|
|
1028
1197
|
encoding = options[:encoding] || document.encoding
|
1029
1198
|
options[:encoding] = encoding
|
1030
1199
|
|
1031
|
-
outstring =
|
1200
|
+
outstring = +""
|
1032
1201
|
outstring.force_encoding(Encoding.find(encoding || "utf-8"))
|
1033
1202
|
io = StringIO.new(outstring)
|
1034
|
-
write_to
|
1203
|
+
write_to(io, options, &block)
|
1035
1204
|
io.string
|
1036
1205
|
end
|
1037
1206
|
|
@@ -1043,7 +1212,7 @@ module Nokogiri
|
|
1043
1212
|
# See Node#write_to for a list of +options+. For formatted output,
|
1044
1213
|
# use Node#to_xhtml instead.
|
1045
1214
|
def to_html(options = {})
|
1046
|
-
to_format
|
1215
|
+
to_format(SaveOptions::DEFAULT_HTML, options)
|
1047
1216
|
end
|
1048
1217
|
|
1049
1218
|
###
|
@@ -1064,7 +1233,7 @@ module Nokogiri
|
|
1064
1233
|
#
|
1065
1234
|
# See Node#write_to for a list of +options+
|
1066
1235
|
def to_xhtml(options = {})
|
1067
|
-
to_format
|
1236
|
+
to_format(SaveOptions::DEFAULT_XHTML, options)
|
1068
1237
|
end
|
1069
1238
|
|
1070
1239
|
###
|
@@ -1112,7 +1281,7 @@ module Nokogiri
|
|
1112
1281
|
#
|
1113
1282
|
# See Node#write_to for a list of +options+
|
1114
1283
|
def write_html_to(io, options = {})
|
1115
|
-
write_format_to
|
1284
|
+
write_format_to(SaveOptions::DEFAULT_HTML, io, options)
|
1116
1285
|
end
|
1117
1286
|
|
1118
1287
|
###
|
@@ -1120,7 +1289,7 @@ module Nokogiri
|
|
1120
1289
|
#
|
1121
1290
|
# See Node#write_to for a list of +options+
|
1122
1291
|
def write_xhtml_to(io, options = {})
|
1123
|
-
write_format_to
|
1292
|
+
write_format_to(SaveOptions::DEFAULT_XHTML, io, options)
|
1124
1293
|
end
|
1125
1294
|
|
1126
1295
|
###
|
@@ -1131,7 +1300,7 @@ module Nokogiri
|
|
1131
1300
|
# See Node#write_to for a list of options
|
1132
1301
|
def write_xml_to(io, options = {})
|
1133
1302
|
options[:save_with] ||= SaveOptions::DEFAULT_XML
|
1134
|
-
write_to
|
1303
|
+
write_to(io, options)
|
1135
1304
|
end
|
1136
1305
|
|
1137
1306
|
def canonicalize(mode = XML::XML_C14N_1_0, inclusive_namespaces = nil, with_comments = false)
|
@@ -1142,7 +1311,7 @@ module Nokogiri
|
|
1142
1311
|
end
|
1143
1312
|
end
|
1144
1313
|
|
1145
|
-
#
|
1314
|
+
# :section:
|
1146
1315
|
|
1147
1316
|
protected
|
1148
1317
|
|
@@ -1160,9 +1329,9 @@ module Nokogiri
|
|
1160
1329
|
return data
|
1161
1330
|
end
|
1162
1331
|
|
1163
|
-
raise ArgumentError,
|
1164
|
-
Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
1165
|
-
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
|
1332
|
+
raise ArgumentError, <<~EOERR
|
1333
|
+
Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
1334
|
+
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
|
1166
1335
|
EOERR
|
1167
1336
|
end
|
1168
1337
|
|
@@ -1171,32 +1340,33 @@ Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
|
1171
1340
|
def keywordify(keywords)
|
1172
1341
|
case keywords
|
1173
1342
|
when Enumerable
|
1174
|
-
|
1343
|
+
keywords
|
1175
1344
|
when String
|
1176
|
-
|
1345
|
+
keywords.scan(/\S+/)
|
1177
1346
|
else
|
1178
|
-
raise ArgumentError
|
1347
|
+
raise ArgumentError,
|
1348
|
+
"Keyword attributes must be passed as either a String or an Enumerable, but received #{keywords.class}"
|
1179
1349
|
end
|
1180
1350
|
end
|
1181
1351
|
|
1182
1352
|
def add_sibling(next_or_previous, node_or_tags)
|
1183
1353
|
raise("Cannot add sibling to a node with no parent") unless parent
|
1184
1354
|
|
1185
|
-
impl =
|
1186
|
-
iter =
|
1355
|
+
impl = next_or_previous == :next ? :add_next_sibling_node : :add_previous_sibling_node
|
1356
|
+
iter = next_or_previous == :next ? :reverse_each : :each
|
1187
1357
|
|
1188
1358
|
node_or_tags = parent.coerce(node_or_tags)
|
1189
1359
|
if node_or_tags.is_a?(XML::NodeSet)
|
1190
1360
|
if text?
|
1191
|
-
pivot = Nokogiri::XML::Node.new
|
1192
|
-
send
|
1361
|
+
pivot = Nokogiri::XML::Node.new("dummy", document)
|
1362
|
+
send(impl, pivot)
|
1193
1363
|
else
|
1194
1364
|
pivot = self
|
1195
1365
|
end
|
1196
|
-
node_or_tags.send(iter) { |n| pivot.send
|
1366
|
+
node_or_tags.send(iter) { |n| pivot.send(impl, n) }
|
1197
1367
|
pivot.unlink if text?
|
1198
1368
|
else
|
1199
|
-
send
|
1369
|
+
send(impl, node_or_tags)
|
1200
1370
|
end
|
1201
1371
|
node_or_tags
|
1202
1372
|
end
|
@@ -1215,19 +1385,18 @@ Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
|
1215
1385
|
return (io << dump_html) if USING_LIBXML_WITH_BROKEN_SERIALIZATION
|
1216
1386
|
|
1217
1387
|
options[:save_with] ||= save_option
|
1218
|
-
write_to
|
1388
|
+
write_to(io, options)
|
1219
1389
|
end
|
1220
1390
|
|
1221
1391
|
def inspect_attributes
|
1222
1392
|
[:name, :namespace, :attribute_nodes, :children]
|
1223
1393
|
end
|
1224
1394
|
|
1225
|
-
|
1226
|
-
IMPLIED_XPATH_CONTEXTS = [".//".freeze].freeze
|
1395
|
+
IMPLIED_XPATH_CONTEXTS = [".//"].freeze
|
1227
1396
|
|
1228
1397
|
def add_child_node_and_reparent_attrs(node)
|
1229
|
-
add_child_node
|
1230
|
-
node.attribute_nodes.find_all { |a| a.name
|
1398
|
+
add_child_node(node)
|
1399
|
+
node.attribute_nodes.find_all { |a| a.name.include?(":") }.each do |attr_node|
|
1231
1400
|
attr_node.remove
|
1232
1401
|
node[attr_node.name] = attr_node.value
|
1233
1402
|
end
|
@@ -1235,3 +1404,5 @@ Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
|
1235
1404
|
end
|
1236
1405
|
end
|
1237
1406
|
end
|
1407
|
+
|
1408
|
+
require_relative "node/save_options"
|