nokogiri 1.11.0.rc1-java → 1.11.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/LICENSE-DEPENDENCIES.md +1015 -947
- data/LICENSE.md +1 -1
- data/README.md +171 -94
- data/ext/java/nokogiri/EncodingHandler.java +78 -59
- data/ext/java/nokogiri/HtmlDocument.java +137 -114
- data/ext/java/nokogiri/HtmlElementDescription.java +104 -87
- data/ext/java/nokogiri/HtmlEntityLookup.java +31 -26
- data/ext/java/nokogiri/HtmlSaxParserContext.java +220 -192
- data/ext/java/nokogiri/HtmlSaxPushParser.java +164 -139
- data/ext/java/nokogiri/NokogiriService.java +597 -526
- data/ext/java/nokogiri/XmlAttr.java +120 -96
- data/ext/java/nokogiri/XmlAttributeDecl.java +97 -76
- data/ext/java/nokogiri/XmlCdata.java +35 -26
- data/ext/java/nokogiri/XmlComment.java +48 -37
- data/ext/java/nokogiri/XmlDocument.java +642 -540
- data/ext/java/nokogiri/XmlDocumentFragment.java +127 -107
- data/ext/java/nokogiri/XmlDtd.java +450 -384
- data/ext/java/nokogiri/XmlElement.java +25 -18
- data/ext/java/nokogiri/XmlElementContent.java +345 -286
- data/ext/java/nokogiri/XmlElementDecl.java +126 -95
- data/ext/java/nokogiri/XmlEntityDecl.java +121 -97
- data/ext/java/nokogiri/XmlEntityReference.java +51 -42
- data/ext/java/nokogiri/XmlNamespace.java +177 -145
- data/ext/java/nokogiri/XmlNode.java +1843 -1590
- data/ext/java/nokogiri/XmlNodeSet.java +361 -299
- data/ext/java/nokogiri/XmlProcessingInstruction.java +49 -39
- data/ext/java/nokogiri/XmlReader.java +513 -418
- data/ext/java/nokogiri/XmlRelaxng.java +92 -72
- data/ext/java/nokogiri/XmlSaxParserContext.java +330 -280
- data/ext/java/nokogiri/XmlSaxPushParser.java +229 -190
- data/ext/java/nokogiri/XmlSchema.java +335 -210
- data/ext/java/nokogiri/XmlSyntaxError.java +113 -87
- data/ext/java/nokogiri/XmlText.java +57 -46
- data/ext/java/nokogiri/XmlXpathContext.java +242 -178
- data/ext/java/nokogiri/XsltStylesheet.java +282 -239
- data/ext/java/nokogiri/internals/ClosedStreamException.java +5 -2
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +203 -160
- data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +17 -10
- data/ext/java/nokogiri/internals/NokogiriBlockingQueueInputStream.java +43 -16
- data/ext/java/nokogiri/internals/NokogiriDomParser.java +65 -50
- data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +107 -88
- data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +25 -18
- data/ext/java/nokogiri/internals/NokogiriHandler.java +316 -254
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +738 -622
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +186 -143
- data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +81 -59
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +66 -49
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +86 -69
- data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +44 -29
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +121 -48
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -22
- data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +25 -17
- data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +57 -42
- data/ext/java/nokogiri/internals/ParserContext.java +206 -179
- data/ext/java/nokogiri/internals/ReaderNode.java +478 -371
- data/ext/java/nokogiri/internals/SaveContextVisitor.java +822 -707
- data/ext/java/nokogiri/internals/SchemaErrorHandler.java +28 -19
- data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +129 -123
- data/ext/java/nokogiri/internals/XmlDeclHandler.java +5 -4
- data/ext/java/nokogiri/internals/XmlDomParserContext.java +208 -177
- data/ext/java/nokogiri/internals/XmlSaxParser.java +24 -17
- data/ext/java/nokogiri/internals/c14n/AttrCompare.java +71 -68
- data/ext/java/nokogiri/internals/c14n/C14nHelper.java +137 -118
- data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +27 -21
- data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +74 -61
- data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +230 -205
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +572 -547
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +17 -10
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +17 -10
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +323 -302
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +232 -219
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +22 -15
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +23 -16
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +23 -16
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +22 -15
- data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +575 -545
- data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +141 -120
- data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +39 -38
- data/ext/java/nokogiri/internals/c14n/Constants.java +13 -10
- data/ext/java/nokogiri/internals/c14n/ElementProxy.java +279 -247
- data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +66 -53
- data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +44 -37
- data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +135 -120
- data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +59 -48
- data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +384 -334
- data/ext/java/nokogiri/internals/c14n/NodeFilter.java +25 -24
- data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +151 -140
- data/ext/java/nokogiri/internals/c14n/XMLUtils.java +456 -423
- data/ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java +1466 -1500
- data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +626 -570
- data/ext/nokogiri/depend +37 -358
- data/ext/nokogiri/extconf.rb +585 -374
- data/ext/nokogiri/html_document.c +78 -82
- data/ext/nokogiri/html_element_description.c +84 -71
- data/ext/nokogiri/html_entity_lookup.c +21 -16
- data/ext/nokogiri/html_sax_parser_context.c +69 -66
- data/ext/nokogiri/html_sax_push_parser.c +42 -34
- data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
- data/ext/nokogiri/nokogiri.c +192 -93
- data/ext/nokogiri/test_global_handlers.c +40 -0
- data/ext/nokogiri/xml_attr.c +15 -15
- 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 +225 -163
- data/ext/nokogiri/xml_document_fragment.c +13 -15
- data/ext/nokogiri/xml_dtd.c +54 -48
- data/ext/nokogiri/xml_element_content.c +30 -27
- data/ext/nokogiri/xml_element_decl.c +22 -22
- data/ext/nokogiri/xml_encoding_handler.c +17 -11
- data/ext/nokogiri/xml_entity_decl.c +32 -30
- data/ext/nokogiri/xml_entity_reference.c +16 -18
- data/ext/nokogiri/xml_namespace.c +56 -49
- data/ext/nokogiri/xml_node.c +338 -286
- data/ext/nokogiri/xml_node_set.c +168 -156
- data/ext/nokogiri/xml_processing_instruction.c +17 -19
- data/ext/nokogiri/xml_reader.c +195 -172
- data/ext/nokogiri/xml_relax_ng.c +52 -28
- data/ext/nokogiri/xml_sax_parser.c +118 -118
- data/ext/nokogiri/xml_sax_parser_context.c +103 -86
- data/ext/nokogiri/xml_sax_push_parser.c +36 -27
- data/ext/nokogiri/xml_schema.c +111 -34
- data/ext/nokogiri/xml_syntax_error.c +42 -21
- data/ext/nokogiri/xml_text.c +13 -17
- data/ext/nokogiri/xml_xpath_context.c +206 -123
- data/ext/nokogiri/xslt_stylesheet.c +158 -161
- data/lib/nokogiri.rb +4 -8
- data/lib/nokogiri/css/parser.rb +62 -62
- data/lib/nokogiri/css/parser.y +2 -2
- data/lib/nokogiri/css/parser_extras.rb +38 -36
- data/lib/nokogiri/css/xpath_visitor.rb +70 -42
- data/lib/nokogiri/extension.rb +26 -0
- data/lib/nokogiri/html/document.rb +12 -26
- data/lib/nokogiri/html/document_fragment.rb +15 -15
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version.rb +2 -148
- data/lib/nokogiri/version/constant.rb +5 -0
- data/lib/nokogiri/version/info.rb +205 -0
- data/lib/nokogiri/xml/builder.rb +2 -2
- data/lib/nokogiri/xml/document.rb +48 -18
- data/lib/nokogiri/xml/document_fragment.rb +4 -6
- data/lib/nokogiri/xml/node.rb +599 -279
- data/lib/nokogiri/xml/parse_options.rb +6 -0
- data/lib/nokogiri/xml/reader.rb +2 -9
- data/lib/nokogiri/xml/relax_ng.rb +6 -2
- data/lib/nokogiri/xml/schema.rb +12 -4
- data/lib/nokogiri/xml/searchable.rb +24 -16
- data/lib/nokogiri/xml/xpath.rb +1 -3
- data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
- metadata +87 -158
- data/ext/nokogiri/html_document.h +0 -10
- data/ext/nokogiri/html_element_description.h +0 -10
- data/ext/nokogiri/html_entity_lookup.h +0 -8
- data/ext/nokogiri/html_sax_parser_context.h +0 -11
- data/ext/nokogiri/html_sax_push_parser.h +0 -9
- data/ext/nokogiri/nokogiri.h +0 -122
- data/ext/nokogiri/xml_attr.h +0 -9
- data/ext/nokogiri/xml_attribute_decl.h +0 -9
- data/ext/nokogiri/xml_cdata.h +0 -9
- data/ext/nokogiri/xml_comment.h +0 -9
- data/ext/nokogiri/xml_document.h +0 -23
- data/ext/nokogiri/xml_document_fragment.h +0 -10
- data/ext/nokogiri/xml_dtd.h +0 -10
- data/ext/nokogiri/xml_element_content.h +0 -10
- data/ext/nokogiri/xml_element_decl.h +0 -9
- data/ext/nokogiri/xml_encoding_handler.h +0 -8
- data/ext/nokogiri/xml_entity_decl.h +0 -10
- data/ext/nokogiri/xml_entity_reference.h +0 -9
- data/ext/nokogiri/xml_io.c +0 -61
- data/ext/nokogiri/xml_io.h +0 -11
- data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
- data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
- data/ext/nokogiri/xml_namespace.h +0 -14
- data/ext/nokogiri/xml_node.h +0 -13
- data/ext/nokogiri/xml_node_set.h +0 -12
- data/ext/nokogiri/xml_processing_instruction.h +0 -9
- data/ext/nokogiri/xml_reader.h +0 -10
- data/ext/nokogiri/xml_relax_ng.h +0 -9
- data/ext/nokogiri/xml_sax_parser.h +0 -39
- data/ext/nokogiri/xml_sax_parser_context.h +0 -10
- data/ext/nokogiri/xml_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_schema.h +0 -9
- data/ext/nokogiri/xml_syntax_error.h +0 -13
- data/ext/nokogiri/xml_text.h +0 -9
- data/ext/nokogiri/xml_xpath_context.h +0 -10
- data/ext/nokogiri/xslt_stylesheet.h +0 -14
|
@@ -141,6 +141,10 @@ module Nokogiri
|
|
|
141
141
|
document.errors = things
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
def fragment(data)
|
|
145
|
+
document.fragment(data)
|
|
146
|
+
end
|
|
147
|
+
|
|
144
148
|
private
|
|
145
149
|
|
|
146
150
|
# fix for issue 770
|
|
@@ -150,12 +154,6 @@ module Nokogiri
|
|
|
150
154
|
%Q{xmlns#{prefix}="#{namespace.href}"}
|
|
151
155
|
end.join ' '
|
|
152
156
|
end
|
|
153
|
-
|
|
154
|
-
def coerce data
|
|
155
|
-
return super unless String === data
|
|
156
|
-
|
|
157
|
-
document.fragment(data).children
|
|
158
|
-
end
|
|
159
157
|
end
|
|
160
158
|
end
|
|
161
159
|
end
|
data/lib/nokogiri/xml/node.rb
CHANGED
|
@@ -1,106 +1,102 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "stringio"
|
|
4
|
+
require "nokogiri/xml/node/save_options"
|
|
5
5
|
|
|
6
6
|
module Nokogiri
|
|
7
7
|
module XML
|
|
8
|
-
|
|
9
|
-
# Nokogiri::XML::Node is your window to the fun filled world of dealing
|
|
10
|
-
#
|
|
11
|
-
#
|
|
8
|
+
##
|
|
9
|
+
# {Nokogiri::XML::Node} is your window to the fun filled world of dealing with XML and HTML
|
|
10
|
+
# tags. A {Nokogiri::XML::Node} may be treated similarly to a hash with regard to attributes. For
|
|
11
|
+
# example:
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
# => <a href
|
|
15
|
-
#
|
|
16
|
-
# => "
|
|
17
|
-
#
|
|
18
|
-
# =>
|
|
19
|
-
#
|
|
20
|
-
# => ["#foo", "link"]
|
|
21
|
-
# irb(main):008:0> node['class'] = 'green'
|
|
22
|
-
# => "green"
|
|
23
|
-
# irb(main):009:0> node
|
|
24
|
-
# => <a href="#foo" id="link" class="green">link</a>
|
|
25
|
-
# irb(main):010:0>
|
|
13
|
+
# node = Nokogiri::XML::DocumentFragment.parse("<a href='#foo' id='link'>link</a>").at_css("a")
|
|
14
|
+
# node.to_html # => "<a href=\"#foo\" id=\"link\">link</a>"
|
|
15
|
+
# node['href'] # => "#foo"
|
|
16
|
+
# node.keys # => ["href", "id"]
|
|
17
|
+
# node.values # => ["#foo", "link"]
|
|
18
|
+
# node['class'] = 'green' # => "green"
|
|
19
|
+
# node.to_html # => "<a href=\"#foo\" id=\"link\" class=\"green\">link</a>"
|
|
26
20
|
#
|
|
27
|
-
# See
|
|
21
|
+
# See the method group entitled "Working With Node Attributes" for the full set of methods.
|
|
28
22
|
#
|
|
29
|
-
# Nokogiri::XML::Node also has methods that let you move around your
|
|
23
|
+
# {Nokogiri::XML::Node} also has methods that let you move around your
|
|
30
24
|
# tree. For navigating your tree, see:
|
|
31
25
|
#
|
|
32
|
-
# *
|
|
33
|
-
# *
|
|
34
|
-
# *
|
|
35
|
-
# *
|
|
36
|
-
#
|
|
26
|
+
# * {#parent}
|
|
27
|
+
# * {#children}
|
|
28
|
+
# * {#next}
|
|
29
|
+
# * {#previous}
|
|
37
30
|
#
|
|
38
31
|
# When printing or otherwise emitting a document or a node (and
|
|
39
32
|
# its subtree), there are a few methods you might want to use:
|
|
40
33
|
#
|
|
41
|
-
# * content, text, inner_text, to_str: emit plaintext
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
# document, meaning that entities will be replaced (e.g., "<"
|
|
45
|
-
# will be replaced with "<"), meaning that any sanitizing will
|
|
46
|
-
# likely be un-done in the output.
|
|
34
|
+
# * {#content}, {#text}, {#inner_text}, {#to_str}: These methods will all <b>emit plaintext</b>,
|
|
35
|
+
# meaning that entities will be replaced (e.g., "<" will be replaced with "<"), meaning
|
|
36
|
+
# that any sanitizing will likely be un-done in the output.
|
|
47
37
|
#
|
|
48
|
-
# * to_s, to_xml, to_html, inner_html:
|
|
38
|
+
# * {#to_s}, {#to_xml}, {#to_html}, {#inner_html}: These methods will all <b>emit
|
|
39
|
+
# properly-escaped markup</b>, meaning that it's suitable for consumption by browsers,
|
|
40
|
+
# parsers, etc.
|
|
49
41
|
#
|
|
50
|
-
#
|
|
51
|
-
# that it's suitable for consumption by browsers, parsers, etc.
|
|
42
|
+
# You may search this node's subtree using {#xpath} and {#css}
|
|
52
43
|
#
|
|
53
|
-
# You may search this node's subtree using Searchable#xpath and Searchable#css
|
|
54
44
|
class Node
|
|
55
45
|
include Nokogiri::XML::PP::Node
|
|
56
46
|
include Nokogiri::XML::Searchable
|
|
57
47
|
include Enumerable
|
|
58
48
|
|
|
59
|
-
# Element node type, see Nokogiri::XML::Node#element?
|
|
60
|
-
ELEMENT_NODE =
|
|
49
|
+
# Element node type, see {Nokogiri::XML::Node#element?}
|
|
50
|
+
ELEMENT_NODE = 1
|
|
61
51
|
# Attribute node type
|
|
62
|
-
ATTRIBUTE_NODE =
|
|
63
|
-
# Text node type, see Nokogiri::XML::Node#text?
|
|
64
|
-
TEXT_NODE =
|
|
65
|
-
# CDATA node type, see Nokogiri::XML::Node#cdata?
|
|
52
|
+
ATTRIBUTE_NODE = 2
|
|
53
|
+
# Text node type, see {Nokogiri::XML::Node#text?}
|
|
54
|
+
TEXT_NODE = 3
|
|
55
|
+
# CDATA node type, see {Nokogiri::XML::Node#cdata?}
|
|
66
56
|
CDATA_SECTION_NODE = 4
|
|
67
57
|
# Entity reference node type
|
|
68
|
-
ENTITY_REF_NODE =
|
|
58
|
+
ENTITY_REF_NODE = 5
|
|
69
59
|
# Entity node type
|
|
70
|
-
ENTITY_NODE =
|
|
60
|
+
ENTITY_NODE = 6
|
|
71
61
|
# PI node type
|
|
72
|
-
PI_NODE =
|
|
73
|
-
# Comment node type, see Nokogiri::XML::Node#comment?
|
|
74
|
-
COMMENT_NODE =
|
|
75
|
-
# Document node type, see Nokogiri::XML::Node#xml?
|
|
76
|
-
DOCUMENT_NODE =
|
|
62
|
+
PI_NODE = 7
|
|
63
|
+
# Comment node type, see {Nokogiri::XML::Node#comment?}
|
|
64
|
+
COMMENT_NODE = 8
|
|
65
|
+
# Document node type, see {Nokogiri::XML::Node#xml?}
|
|
66
|
+
DOCUMENT_NODE = 9
|
|
77
67
|
# Document type node type
|
|
78
68
|
DOCUMENT_TYPE_NODE = 10
|
|
79
69
|
# Document fragment node type
|
|
80
70
|
DOCUMENT_FRAG_NODE = 11
|
|
81
71
|
# Notation node type
|
|
82
|
-
NOTATION_NODE =
|
|
83
|
-
# HTML document node type, see Nokogiri::XML::Node#html?
|
|
72
|
+
NOTATION_NODE = 12
|
|
73
|
+
# HTML document node type, see {Nokogiri::XML::Node#html?}
|
|
84
74
|
HTML_DOCUMENT_NODE = 13
|
|
85
75
|
# DTD node type
|
|
86
|
-
DTD_NODE =
|
|
76
|
+
DTD_NODE = 14
|
|
87
77
|
# Element declaration type
|
|
88
|
-
ELEMENT_DECL =
|
|
78
|
+
ELEMENT_DECL = 15
|
|
89
79
|
# Attribute declaration type
|
|
90
|
-
ATTRIBUTE_DECL =
|
|
80
|
+
ATTRIBUTE_DECL = 16
|
|
91
81
|
# Entity declaration type
|
|
92
|
-
ENTITY_DECL =
|
|
82
|
+
ENTITY_DECL = 17
|
|
93
83
|
# Namespace declaration type
|
|
94
|
-
NAMESPACE_DECL =
|
|
84
|
+
NAMESPACE_DECL = 18
|
|
95
85
|
# XInclude start type
|
|
96
|
-
XINCLUDE_START =
|
|
86
|
+
XINCLUDE_START = 19
|
|
97
87
|
# XInclude end type
|
|
98
|
-
XINCLUDE_END =
|
|
88
|
+
XINCLUDE_END = 20
|
|
99
89
|
# DOCB document node type
|
|
100
90
|
DOCB_DOCUMENT_NODE = 21
|
|
101
91
|
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
##
|
|
93
|
+
# Create a new node with +name+ sharing GC lifecycle with +document+.
|
|
94
|
+
# @param name [String]
|
|
95
|
+
# @param document [Nokogiri::XML::Document]
|
|
96
|
+
# @return [Nokogiri::XML::Node]
|
|
97
|
+
# @see Nokogiri::XML::Node.new
|
|
98
|
+
def initialize(name, document)
|
|
99
|
+
# This is intentionally empty.
|
|
104
100
|
end
|
|
105
101
|
|
|
106
102
|
###
|
|
@@ -109,24 +105,18 @@ module Nokogiri
|
|
|
109
105
|
document.decorate(self)
|
|
110
106
|
end
|
|
111
107
|
|
|
108
|
+
# @!group Searching via XPath or CSS Queries
|
|
109
|
+
|
|
112
110
|
###
|
|
113
111
|
# Search this node's immediate children using CSS selector +selector+
|
|
114
|
-
def >
|
|
112
|
+
def >(selector)
|
|
115
113
|
ns = document.root.namespaces
|
|
116
114
|
xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first
|
|
117
115
|
end
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
# Get the attribute value for the attribute +name+
|
|
121
|
-
def [] name
|
|
122
|
-
get(name.to_s)
|
|
123
|
-
end
|
|
117
|
+
# @!endgroup
|
|
124
118
|
|
|
125
|
-
|
|
126
|
-
# Set the attribute value for the attribute +name+ to +value+
|
|
127
|
-
def []= name, value
|
|
128
|
-
set name.to_s, value.to_s
|
|
129
|
-
end
|
|
119
|
+
# @!group Manipulating Document Structure
|
|
130
120
|
|
|
131
121
|
###
|
|
132
122
|
# Add +node_or_tags+ as a child of this Node.
|
|
@@ -135,7 +125,7 @@ module Nokogiri
|
|
|
135
125
|
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
|
136
126
|
#
|
|
137
127
|
# Also see related method +<<+.
|
|
138
|
-
def add_child
|
|
128
|
+
def add_child(node_or_tags)
|
|
139
129
|
node_or_tags = coerce(node_or_tags)
|
|
140
130
|
if node_or_tags.is_a?(XML::NodeSet)
|
|
141
131
|
node_or_tags.each { |n| add_child_node_and_reparent_attrs n }
|
|
@@ -152,7 +142,7 @@ module Nokogiri
|
|
|
152
142
|
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
|
153
143
|
#
|
|
154
144
|
# Also see related method +add_child+.
|
|
155
|
-
def prepend_child
|
|
145
|
+
def prepend_child(node_or_tags)
|
|
156
146
|
if first = children.first
|
|
157
147
|
# Mimic the error add_child would raise.
|
|
158
148
|
raise RuntimeError, "Document already has a root node" if document? && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
|
@@ -162,7 +152,6 @@ module Nokogiri
|
|
|
162
152
|
end
|
|
163
153
|
end
|
|
164
154
|
|
|
165
|
-
|
|
166
155
|
###
|
|
167
156
|
# Add html around this node
|
|
168
157
|
#
|
|
@@ -181,7 +170,7 @@ module Nokogiri
|
|
|
181
170
|
# Returns self, to support chaining of calls (e.g., root << child1 << child2)
|
|
182
171
|
#
|
|
183
172
|
# Also see related method +add_child+.
|
|
184
|
-
def <<
|
|
173
|
+
def <<(node_or_tags)
|
|
185
174
|
add_child node_or_tags
|
|
186
175
|
self
|
|
187
176
|
end
|
|
@@ -193,7 +182,7 @@ module Nokogiri
|
|
|
193
182
|
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
|
194
183
|
#
|
|
195
184
|
# Also see related method +before+.
|
|
196
|
-
def add_previous_sibling
|
|
185
|
+
def add_previous_sibling(node_or_tags)
|
|
197
186
|
raise ArgumentError.new("A document may not have multiple root nodes.") if (parent && parent.document?) && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
|
198
187
|
|
|
199
188
|
add_sibling :previous, node_or_tags
|
|
@@ -206,7 +195,7 @@ module Nokogiri
|
|
|
206
195
|
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
|
207
196
|
#
|
|
208
197
|
# Also see related method +after+.
|
|
209
|
-
def add_next_sibling
|
|
198
|
+
def add_next_sibling(node_or_tags)
|
|
210
199
|
raise ArgumentError.new("A document may not have multiple root nodes.") if (parent && parent.document?) && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
|
211
200
|
|
|
212
201
|
add_sibling :next, node_or_tags
|
|
@@ -219,7 +208,7 @@ module Nokogiri
|
|
|
219
208
|
# Returns self, to support chaining of calls.
|
|
220
209
|
#
|
|
221
210
|
# Also see related method +add_previous_sibling+.
|
|
222
|
-
def before
|
|
211
|
+
def before(node_or_tags)
|
|
223
212
|
add_previous_sibling node_or_tags
|
|
224
213
|
self
|
|
225
214
|
end
|
|
@@ -231,7 +220,7 @@ module Nokogiri
|
|
|
231
220
|
# Returns self, to support chaining of calls.
|
|
232
221
|
#
|
|
233
222
|
# Also see related method +add_next_sibling+.
|
|
234
|
-
def after
|
|
223
|
+
def after(node_or_tags)
|
|
235
224
|
add_next_sibling node_or_tags
|
|
236
225
|
self
|
|
237
226
|
end
|
|
@@ -243,7 +232,7 @@ module Nokogiri
|
|
|
243
232
|
# Returns self.
|
|
244
233
|
#
|
|
245
234
|
# Also see related method +children=+
|
|
246
|
-
def inner_html=
|
|
235
|
+
def inner_html=(node_or_tags)
|
|
247
236
|
self.children = node_or_tags
|
|
248
237
|
self
|
|
249
238
|
end
|
|
@@ -255,7 +244,7 @@ module Nokogiri
|
|
|
255
244
|
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
|
256
245
|
#
|
|
257
246
|
# Also see related method +inner_html=+
|
|
258
|
-
def children=
|
|
247
|
+
def children=(node_or_tags)
|
|
259
248
|
node_or_tags = coerce(node_or_tags)
|
|
260
249
|
children.unlink
|
|
261
250
|
if node_or_tags.is_a?(XML::NodeSet)
|
|
@@ -273,19 +262,21 @@ module Nokogiri
|
|
|
273
262
|
# Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
|
|
274
263
|
#
|
|
275
264
|
# Also see related method +swap+.
|
|
276
|
-
def replace
|
|
265
|
+
def replace(node_or_tags)
|
|
266
|
+
raise("Cannot replace a node with no parent") unless parent
|
|
267
|
+
|
|
277
268
|
# We cannot replace a text node directly, otherwise libxml will return
|
|
278
269
|
# an internal error at parser.c:13031, I don't know exactly why
|
|
279
270
|
# libxml is trying to find a parent node that is an element or document
|
|
280
271
|
# so I can't tell if this is bug in libxml or not. issue #775.
|
|
281
272
|
if text?
|
|
282
|
-
replacee = Nokogiri::XML::Node.new
|
|
273
|
+
replacee = Nokogiri::XML::Node.new "dummy", document
|
|
283
274
|
add_previous_sibling_node replacee
|
|
284
275
|
unlink
|
|
285
276
|
return replacee.replace node_or_tags
|
|
286
277
|
end
|
|
287
278
|
|
|
288
|
-
node_or_tags = coerce(node_or_tags)
|
|
279
|
+
node_or_tags = parent.coerce(node_or_tags)
|
|
289
280
|
|
|
290
281
|
if node_or_tags.is_a?(XML::NodeSet)
|
|
291
282
|
node_or_tags.each { |n| add_previous_sibling n }
|
|
@@ -303,33 +294,98 @@ module Nokogiri
|
|
|
303
294
|
# Returns self, to support chaining of calls.
|
|
304
295
|
#
|
|
305
296
|
# Also see related method +replace+.
|
|
306
|
-
def swap
|
|
297
|
+
def swap(node_or_tags)
|
|
307
298
|
replace node_or_tags
|
|
308
299
|
self
|
|
309
300
|
end
|
|
310
301
|
|
|
311
|
-
|
|
312
|
-
|
|
302
|
+
####
|
|
303
|
+
# Set the Node's content to a Text node containing +string+. The string gets XML escaped, not interpreted as markup.
|
|
304
|
+
def content=(string)
|
|
305
|
+
self.native_content = encode_special_chars(string.to_s)
|
|
306
|
+
end
|
|
313
307
|
|
|
314
|
-
|
|
315
|
-
#
|
|
316
|
-
|
|
317
|
-
|
|
308
|
+
###
|
|
309
|
+
# Set the parent Node for this Node
|
|
310
|
+
def parent=(parent_node)
|
|
311
|
+
parent_node.add_child(self)
|
|
312
|
+
parent_node
|
|
313
|
+
end
|
|
318
314
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
315
|
+
###
|
|
316
|
+
# Adds a default namespace supplied as a string +url+ href, to self.
|
|
317
|
+
# The consequence is as an xmlns attribute with supplied argument were
|
|
318
|
+
# present in parsed XML. A default namespace set with this method will
|
|
319
|
+
# now show up in #attributes, but when this node is serialized to XML an
|
|
320
|
+
# "xmlns" attribute will appear. See also #namespace and #namespace=
|
|
321
|
+
def default_namespace=(url)
|
|
322
|
+
add_namespace_definition(nil, url)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
###
|
|
326
|
+
# Set the default namespace on this node (as would be defined with an
|
|
327
|
+
# "xmlns=" attribute in XML source), as a Namespace object +ns+. Note that
|
|
328
|
+
# a Namespace added this way will NOT be serialized as an xmlns attribute
|
|
329
|
+
# for this node. You probably want #default_namespace= instead, or perhaps
|
|
330
|
+
# #add_namespace_definition with a nil prefix argument.
|
|
331
|
+
def namespace=(ns)
|
|
332
|
+
return set_namespace(ns) unless ns
|
|
333
|
+
|
|
334
|
+
unless Nokogiri::XML::Namespace === ns
|
|
335
|
+
raise TypeError, "#{ns.class} can't be coerced into Nokogiri::XML::Namespace"
|
|
336
|
+
end
|
|
337
|
+
if ns.document != document
|
|
338
|
+
raise ArgumentError, "namespace must be declared on the same document"
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
set_namespace ns
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
###
|
|
345
|
+
# Do xinclude substitution on the subtree below node. If given a block, a
|
|
346
|
+
# Nokogiri::XML::ParseOptions object initialized from +options+, will be
|
|
347
|
+
# passed to it, allowing more convenient modification of the parser options.
|
|
348
|
+
def do_xinclude(options = XML::ParseOptions::DEFAULT_XML)
|
|
349
|
+
options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
|
|
350
|
+
|
|
351
|
+
# give options to user
|
|
352
|
+
yield options if block_given?
|
|
353
|
+
|
|
354
|
+
# call c extension
|
|
355
|
+
process_xincludes(options.to_i)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
alias :next :next_sibling
|
|
359
|
+
alias :previous :previous_sibling
|
|
360
|
+
alias :next= :add_next_sibling
|
|
361
|
+
alias :previous= :add_previous_sibling
|
|
362
|
+
alias :remove :unlink
|
|
363
|
+
alias :name= :node_name=
|
|
364
|
+
alias :add_namespace :add_namespace_definition
|
|
365
|
+
|
|
366
|
+
# @!endgroup
|
|
367
|
+
|
|
368
|
+
alias :text :content
|
|
369
|
+
alias :inner_text :content
|
|
370
|
+
alias :name :node_name
|
|
371
|
+
alias :type :node_type
|
|
372
|
+
alias :to_str :text
|
|
373
|
+
alias :clone :dup
|
|
374
|
+
alias :elements :element_children
|
|
375
|
+
|
|
376
|
+
# @!group Working With Node Attributes
|
|
377
|
+
|
|
378
|
+
###
|
|
379
|
+
# Get the attribute value for the attribute +name+
|
|
380
|
+
def [](name)
|
|
381
|
+
get(name.to_s)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
###
|
|
385
|
+
# Set the attribute value for the attribute +name+ to +value+
|
|
386
|
+
def []=(name, value)
|
|
387
|
+
set name.to_s, value.to_s
|
|
388
|
+
end
|
|
333
389
|
|
|
334
390
|
####
|
|
335
391
|
# Returns a hash containing the node's attributes. The key is
|
|
@@ -370,82 +426,366 @@ module Nokogiri
|
|
|
370
426
|
end
|
|
371
427
|
|
|
372
428
|
###
|
|
373
|
-
#
|
|
374
|
-
|
|
429
|
+
# Remove the attribute named +name+
|
|
430
|
+
def remove_attribute(name)
|
|
431
|
+
attr = attributes[name].remove if key? name
|
|
432
|
+
clear_xpath_context if Nokogiri.jruby?
|
|
433
|
+
attr
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
# Get the CSS class names of a Node.
|
|
437
|
+
#
|
|
438
|
+
# This is a convenience function and is equivalent to:
|
|
439
|
+
# node.kwattr_values("class")
|
|
440
|
+
#
|
|
441
|
+
# @see #kwattr_values
|
|
442
|
+
# @see #add_class
|
|
443
|
+
# @see #append_class
|
|
444
|
+
# @see #remove_class
|
|
445
|
+
#
|
|
446
|
+
# @return [Array<String>]
|
|
447
|
+
#
|
|
448
|
+
# The CSS classes present in the Node's +class+ attribute. If
|
|
449
|
+
# the attribute is empty or non-existent, the return value is
|
|
450
|
+
# an empty array.
|
|
451
|
+
#
|
|
452
|
+
# @example
|
|
453
|
+
# node # => <div class="section title header"></div>
|
|
454
|
+
# node.classes # => ["section", "title", "header"]
|
|
455
|
+
#
|
|
375
456
|
def classes
|
|
376
|
-
|
|
457
|
+
kwattr_values("class")
|
|
377
458
|
end
|
|
378
459
|
|
|
379
|
-
|
|
380
|
-
#
|
|
381
|
-
#
|
|
382
|
-
#
|
|
383
|
-
#
|
|
460
|
+
# Ensure HTML CSS classes are present on a +Node+. Any CSS
|
|
461
|
+
# classes in +names+ that already exist in the +Node+'s +class+
|
|
462
|
+
# attribute are _not_ added. Note that any existing duplicates
|
|
463
|
+
# in the +class+ attribute are not removed. Compare with
|
|
464
|
+
# {#append_class}.
|
|
465
|
+
#
|
|
466
|
+
# This is a convenience function and is equivalent to:
|
|
467
|
+
# node.kwattr_add("class", names)
|
|
468
|
+
#
|
|
469
|
+
# @see #kwattr_add
|
|
470
|
+
# @see #classes
|
|
471
|
+
# @see #append_class
|
|
472
|
+
# @see #remove_class
|
|
384
473
|
#
|
|
385
|
-
#
|
|
386
|
-
#
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
474
|
+
# @param names [String, Array<String>]
|
|
475
|
+
#
|
|
476
|
+
# CSS class names to be added to the Node's +class+
|
|
477
|
+
# attribute. May be a string containing whitespace-delimited
|
|
478
|
+
# names, or an Array of String names. Any class names already
|
|
479
|
+
# present will not be added. Any class names not present will
|
|
480
|
+
# be added. If no +class+ attribute exists, one is created.
|
|
481
|
+
#
|
|
482
|
+
# @return [Node] Returns +self+ for ease of chaining method calls.
|
|
483
|
+
#
|
|
484
|
+
# @example Ensure that a +Node+ has CSS class "section"
|
|
485
|
+
# node # => <div></div>
|
|
486
|
+
# node.add_class("section") # => <div class="section"></div>
|
|
487
|
+
# node.add_class("section") # => <div class="section"></div> # duplicate not added
|
|
488
|
+
#
|
|
489
|
+
# @example Ensure that a +Node+ has CSS classes "section" and "header", via a String argument.
|
|
490
|
+
# node # => <div class="section section"></div>
|
|
491
|
+
# node.add_class("section header") # => <div class="section section header"></div>
|
|
492
|
+
# # Note that the CSS class "section" is not added because it is already present.
|
|
493
|
+
# # Note also that the pre-existing duplicate CSS class "section" is not removed.
|
|
494
|
+
#
|
|
495
|
+
# @example Ensure that a +Node+ has CSS classes "section" and "header", via an Array argument.
|
|
496
|
+
# node # => <div></div>
|
|
497
|
+
# node.add_class(["section", "header"]) # => <div class="section header"></div>
|
|
498
|
+
#
|
|
499
|
+
def add_class(names)
|
|
500
|
+
kwattr_add("class", names)
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
# Add HTML CSS classes to a +Node+, regardless of
|
|
504
|
+
# duplication. Compare with {#add_class}.
|
|
505
|
+
#
|
|
506
|
+
# This is a convenience function and is equivalent to:
|
|
507
|
+
# node.kwattr_append("class", names)
|
|
508
|
+
#
|
|
509
|
+
# @see #kwattr_append
|
|
510
|
+
# @see #classes
|
|
511
|
+
# @see #add_class
|
|
512
|
+
# @see #remove_class
|
|
513
|
+
#
|
|
514
|
+
# @param names [String, Array<String>]
|
|
515
|
+
#
|
|
516
|
+
# CSS class names to be appended to the Node's +class+
|
|
517
|
+
# attribute. May be a string containing whitespace-delimited
|
|
518
|
+
# names, or an Array of String names. All class names passed
|
|
519
|
+
# in will be appended to the +class+ attribute even if they
|
|
520
|
+
# are already present in the attribute value. If no +class+
|
|
521
|
+
# attribute exists, one is created.
|
|
522
|
+
#
|
|
523
|
+
# @return [Node] Returns +self+ for ease of chaining method calls.
|
|
524
|
+
#
|
|
525
|
+
# @example Append "section" to a +Node+'s CSS +class+ attriubute
|
|
526
|
+
# node # => <div></div>
|
|
527
|
+
# node.append_class("section") # => <div class="section"></div>
|
|
528
|
+
# node.append_class("section") # => <div class="section section"></div> # duplicate added!
|
|
529
|
+
#
|
|
530
|
+
# @example Append "section" and "header" to a +Node+'s CSS +class+ attribute, via a String argument.
|
|
531
|
+
# node # => <div class="section section"></div>
|
|
532
|
+
# node.append_class("section header") # => <div class="section section section header"></div>
|
|
533
|
+
# # Note that the CSS class "section" is appended even though it is already present.
|
|
534
|
+
#
|
|
535
|
+
# @example Append "section" and "header" to a +Node+'s CSS +class+ attribute, via an Array argument.
|
|
536
|
+
# node # => <div></div>
|
|
537
|
+
# node.append_class(["section", "header"]) # => <div class="section header"></div>
|
|
538
|
+
# node.append_class(["section", "header"]) # => <div class="section header section header"></div>
|
|
539
|
+
#
|
|
540
|
+
def append_class(names)
|
|
541
|
+
kwattr_append("class", names)
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
# Remove HTML CSS classes from a +Node+. Any CSS classes in +names+ that
|
|
545
|
+
# exist in the +Node+'s +class+ attribute are removed, including any
|
|
546
|
+
# multiple entries.
|
|
547
|
+
#
|
|
548
|
+
# If no CSS classes remain after this operation, or if +names+ is
|
|
549
|
+
# +nil+, the +class+ attribute is deleted from the node.
|
|
550
|
+
#
|
|
551
|
+
# This is a convenience function and is equivalent to:
|
|
552
|
+
# node.kwattr_remove("class", names)
|
|
553
|
+
#
|
|
554
|
+
# @see #kwattr_remove
|
|
555
|
+
# @see #classes
|
|
556
|
+
# @see #add_class
|
|
557
|
+
# @see #append_class
|
|
558
|
+
#
|
|
559
|
+
# @param names [String, Array<String>]
|
|
560
|
+
#
|
|
561
|
+
# CSS class names to be removed from the Node's +class+ attribute. May
|
|
562
|
+
# be a string containing whitespace-delimited names, or an Array of
|
|
563
|
+
# String names. Any class names already present will be removed. If no
|
|
564
|
+
# CSS classes remain, the +class+ attribute is deleted.
|
|
565
|
+
#
|
|
566
|
+
# @return [Node] Returns +self+ for ease of chaining method calls.
|
|
567
|
+
#
|
|
568
|
+
# @example
|
|
569
|
+
# node # => <div class="section header"></div>
|
|
570
|
+
# node.remove_class("section") # => <div class="header"></div>
|
|
571
|
+
# node.remove_class("header") # => <div></div> # attribute is deleted when empty
|
|
572
|
+
#
|
|
573
|
+
def remove_class(names = nil)
|
|
574
|
+
kwattr_remove("class", names)
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
# Retrieve values from a keyword attribute of a Node.
|
|
578
|
+
#
|
|
579
|
+
# A "keyword attribute" is a node attribute that contains a set
|
|
580
|
+
# of space-delimited values. Perhaps the most familiar example
|
|
581
|
+
# of this is the HTML +class+ attribute used to contain CSS
|
|
582
|
+
# classes. But other keyword attributes exist, for instance
|
|
583
|
+
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
|
584
|
+
#
|
|
585
|
+
# @see #classes
|
|
586
|
+
# @see #kwattr_add
|
|
587
|
+
# @see #kwattr_append
|
|
588
|
+
# @see #kwattr_remove
|
|
589
|
+
#
|
|
590
|
+
# @param attribute_name [String] The name of the keyword attribute to be inspected.
|
|
591
|
+
#
|
|
592
|
+
# @return [Array<String>]
|
|
593
|
+
#
|
|
594
|
+
# The values present in the Node's +attribute_name+
|
|
595
|
+
# attribute. If the attribute is empty or non-existent, the
|
|
596
|
+
# return value is an empty array.
|
|
597
|
+
#
|
|
598
|
+
# @example
|
|
599
|
+
# node # => <a rel="nofollow noopener external">link</a>
|
|
600
|
+
# node.kwattr_values("rel") # => ["nofollow", "noopener", "external"]
|
|
601
|
+
#
|
|
602
|
+
# @since v1.11.0
|
|
603
|
+
#
|
|
604
|
+
def kwattr_values(attribute_name)
|
|
605
|
+
keywordify(get_attribute(attribute_name) || [])
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
# Ensure that values are present in a keyword attribute.
|
|
609
|
+
#
|
|
610
|
+
# Any values in +keywords+ that already exist in the +Node+'s
|
|
611
|
+
# attribute values are _not_ added. Note that any existing
|
|
612
|
+
# duplicates in the attribute values are not removed. Compare
|
|
613
|
+
# with {#kwattr_append}.
|
|
614
|
+
#
|
|
615
|
+
# A "keyword attribute" is a node attribute that contains a set
|
|
616
|
+
# of space-delimited values. Perhaps the most familiar example
|
|
617
|
+
# of this is the HTML +class+ attribute used to contain CSS
|
|
618
|
+
# classes. But other keyword attributes exist, for instance
|
|
619
|
+
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
|
620
|
+
#
|
|
621
|
+
# @see #add_class
|
|
622
|
+
# @see #kwattr_values
|
|
623
|
+
# @see #kwattr_append
|
|
624
|
+
# @see #kwattr_remove
|
|
625
|
+
#
|
|
626
|
+
# @param attribute_name [String] The name of the keyword attribute to be modified.
|
|
627
|
+
#
|
|
628
|
+
# @param keywords [String, Array<String>]
|
|
629
|
+
#
|
|
630
|
+
# Keywords to be added to the attribute named
|
|
631
|
+
# +attribute_name+. May be a string containing
|
|
632
|
+
# whitespace-delimited values, or an Array of String
|
|
633
|
+
# values. Any values already present will not be added. Any
|
|
634
|
+
# values not present will be added. If the named attribute
|
|
635
|
+
# does not exist, it is created.
|
|
636
|
+
#
|
|
637
|
+
# @return [Node] Returns +self+ for ease of chaining method calls.
|
|
638
|
+
#
|
|
639
|
+
# @example Ensure that a +Node+ has "nofollow" in its +rel+ attribute.
|
|
640
|
+
# node # => <a></a>
|
|
641
|
+
# node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a>
|
|
642
|
+
# node.kwattr_add("rel", "nofollow") # => <a rel="nofollow"></a> # duplicate not added
|
|
643
|
+
#
|
|
644
|
+
# @example Ensure that a +Node+ has "nofollow" and "noreferrer" in its +rel+ attribute, via a String argument.
|
|
645
|
+
# node # => <a rel="nofollow nofollow"></a>
|
|
646
|
+
# node.kwattr_add("rel", "nofollow noreferrer") # => <a rel="nofollow nofollow noreferrer"></a>
|
|
647
|
+
# # Note that "nofollow" is not added because it is already present.
|
|
648
|
+
# # Note also that the pre-existing duplicate "nofollow" is not removed.
|
|
649
|
+
#
|
|
650
|
+
# @example Ensure that a +Node+ has "nofollow" and "noreferrer" in its +rel+ attribute, via an Array argument.
|
|
651
|
+
# node # => <a></a>
|
|
652
|
+
# node.kwattr_add("rel", ["nofollow", "noreferrer"]) # => <a rel="nofollow noreferrer"></a>
|
|
653
|
+
#
|
|
654
|
+
# @since v1.11.0
|
|
655
|
+
#
|
|
656
|
+
def kwattr_add(attribute_name, keywords)
|
|
657
|
+
keywords = keywordify(keywords)
|
|
658
|
+
current_kws = kwattr_values(attribute_name)
|
|
659
|
+
new_kws = (current_kws + (keywords - current_kws)).join(" ")
|
|
660
|
+
set_attribute(attribute_name, new_kws)
|
|
390
661
|
self
|
|
391
662
|
end
|
|
392
663
|
|
|
393
|
-
|
|
394
|
-
#
|
|
395
|
-
#
|
|
396
|
-
#
|
|
397
|
-
#
|
|
664
|
+
# Add keywords to a Node's keyword attribute, regardless of
|
|
665
|
+
# duplication. Compare with {#kwattr_add}.
|
|
666
|
+
#
|
|
667
|
+
# A "keyword attribute" is a node attribute that contains a set
|
|
668
|
+
# of space-delimited values. Perhaps the most familiar example
|
|
669
|
+
# of this is the HTML +class+ attribute used to contain CSS
|
|
670
|
+
# classes. But other keyword attributes exist, for instance
|
|
671
|
+
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
|
672
|
+
#
|
|
673
|
+
# @see #append_class
|
|
674
|
+
# @see #kwattr_values
|
|
675
|
+
# @see #kwattr_add
|
|
676
|
+
# @see #kwattr_remove
|
|
398
677
|
#
|
|
399
|
-
#
|
|
400
|
-
#
|
|
401
|
-
|
|
402
|
-
|
|
678
|
+
# @param attribute_name [String] The name of the keyword attribute to be modified.
|
|
679
|
+
#
|
|
680
|
+
# @param keywords [String, Array<String>]
|
|
681
|
+
#
|
|
682
|
+
# Keywords to be added to the attribute named
|
|
683
|
+
# +attribute_name+. May be a string containing
|
|
684
|
+
# whitespace-delimited values, or an Array of String
|
|
685
|
+
# values. All values passed in will be appended to the named
|
|
686
|
+
# attribute even if they are already present in the
|
|
687
|
+
# attribute. If the named attribute does not exist, it is
|
|
688
|
+
# created.
|
|
689
|
+
#
|
|
690
|
+
# @return [Node] Returns +self+ for ease of chaining method calls.
|
|
691
|
+
#
|
|
692
|
+
# @example Append "nofollow" to the +rel+ attribute.
|
|
693
|
+
# node # => <a></a>
|
|
694
|
+
# node.kwattr_append("rel", "nofollow") # => <a rel="nofollow"></a>
|
|
695
|
+
# node.kwattr_append("rel", "nofollow") # => <a rel="nofollow nofollow"></a> # duplicate added!
|
|
696
|
+
#
|
|
697
|
+
# @example Append "nofollow" and "noreferrer" to the +rel+ attribute, via a String argument.
|
|
698
|
+
# node # => <a rel="nofollow"></a>
|
|
699
|
+
# node.kwattr_append("rel", "nofollow noreferrer") # => <a rel="nofollow nofollow noreferrer"></a>
|
|
700
|
+
# # Note that "nofollow" is appended even though it is already present.
|
|
701
|
+
#
|
|
702
|
+
# @example Append "nofollow" and "noreferrer" to the +rel+ attribute, via an Array argument.
|
|
703
|
+
# node # => <a></a>
|
|
704
|
+
# node.kwattr_append("rel", ["nofollow", "noreferrer"]) # => <a rel="nofollow noreferrer"></a>
|
|
705
|
+
#
|
|
706
|
+
# @since v1.11.0
|
|
707
|
+
#
|
|
708
|
+
def kwattr_append(attribute_name, keywords)
|
|
709
|
+
keywords = keywordify(keywords)
|
|
710
|
+
current_kws = kwattr_values(attribute_name)
|
|
711
|
+
new_kws = (current_kws + keywords).join(" ")
|
|
712
|
+
set_attribute(attribute_name, new_kws)
|
|
403
713
|
self
|
|
404
714
|
end
|
|
405
715
|
|
|
406
|
-
|
|
407
|
-
#
|
|
408
|
-
#
|
|
409
|
-
# they are all removed.
|
|
716
|
+
# Remove keywords from a keyword attribute. Any matching
|
|
717
|
+
# keywords that exist in the named attribute are removed,
|
|
718
|
+
# including any multiple entries.
|
|
410
719
|
#
|
|
411
|
-
#
|
|
412
|
-
#
|
|
720
|
+
# If no keywords remain after this operation, or if +keywords+
|
|
721
|
+
# is +nil+, the attribute is deleted from the node.
|
|
413
722
|
#
|
|
414
|
-
#
|
|
415
|
-
#
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
723
|
+
# A "keyword attribute" is a node attribute that contains a set
|
|
724
|
+
# of space-delimited values. Perhaps the most familiar example
|
|
725
|
+
# of this is the HTML +class+ attribute used to contain CSS
|
|
726
|
+
# classes. But other keyword attributes exist, for instance
|
|
727
|
+
# [`rel`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).
|
|
728
|
+
#
|
|
729
|
+
# @see #remove_class
|
|
730
|
+
# @see #kwattr_values
|
|
731
|
+
# @see #kwattr_add
|
|
732
|
+
# @see #kwattr_append
|
|
733
|
+
#
|
|
734
|
+
# @param attribute_name [String] The name of the keyword attribute to be modified.
|
|
735
|
+
#
|
|
736
|
+
# @param keywords [String, Array<String>]
|
|
737
|
+
#
|
|
738
|
+
# Keywords to be removed from the attribute named
|
|
739
|
+
# +attribute_name+. May be a string containing
|
|
740
|
+
# whitespace-delimited values, or an Array of String
|
|
741
|
+
# values. Any keywords present in the named attribute will be
|
|
742
|
+
# removed. If no keywords remain, or if +keywords+ is nil, the
|
|
743
|
+
# attribute is deleted.
|
|
744
|
+
#
|
|
745
|
+
# @return [Node] Returns +self+ for ease of chaining method calls.
|
|
746
|
+
#
|
|
747
|
+
# @example
|
|
748
|
+
# node # => <a rel="nofollow noreferrer">link</a>
|
|
749
|
+
# node.kwattr_remove("rel", "nofollow") # => <a rel="noreferrer">link</a>
|
|
750
|
+
# node.kwattr_remove("rel", "noreferrer") # => <a>link</a> # attribute is deleted when empty
|
|
751
|
+
#
|
|
752
|
+
# @since v1.11.0
|
|
753
|
+
#
|
|
754
|
+
def kwattr_remove(attribute_name, keywords)
|
|
755
|
+
if keywords.nil?
|
|
756
|
+
remove_attribute(attribute_name)
|
|
757
|
+
return self
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
keywords = keywordify(keywords)
|
|
761
|
+
current_kws = kwattr_values(attribute_name)
|
|
762
|
+
new_kws = current_kws - keywords
|
|
763
|
+
if new_kws.empty?
|
|
764
|
+
remove_attribute(attribute_name)
|
|
424
765
|
else
|
|
425
|
-
|
|
766
|
+
set_attribute(attribute_name, new_kws.join(" "))
|
|
426
767
|
end
|
|
427
768
|
self
|
|
428
769
|
end
|
|
429
770
|
|
|
430
|
-
###
|
|
431
|
-
# Remove the attribute named +name+
|
|
432
|
-
def remove_attribute name
|
|
433
|
-
attr = attributes[name].remove if key? name
|
|
434
|
-
clear_xpath_context if Nokogiri.jruby?
|
|
435
|
-
attr
|
|
436
|
-
end
|
|
437
771
|
alias :delete :remove_attribute
|
|
772
|
+
alias :get_attribute :[]
|
|
773
|
+
alias :attr :[]
|
|
774
|
+
alias :set_attribute :[]=
|
|
775
|
+
alias :has_attribute? :key?
|
|
776
|
+
|
|
777
|
+
# @!endgroup
|
|
438
778
|
|
|
439
779
|
###
|
|
440
780
|
# Returns true if this Node matches +selector+
|
|
441
|
-
def matches?
|
|
781
|
+
def matches?(selector)
|
|
442
782
|
ancestors.last.search(selector).include?(self)
|
|
443
783
|
end
|
|
444
784
|
|
|
445
785
|
###
|
|
446
786
|
# Create a DocumentFragment containing +tags+ that is relative to _this_
|
|
447
787
|
# context node.
|
|
448
|
-
def fragment
|
|
788
|
+
def fragment(tags)
|
|
449
789
|
type = document.html? ? Nokogiri::HTML : Nokogiri::XML
|
|
450
790
|
type::DocumentFragment.new(document, tags, self)
|
|
451
791
|
end
|
|
@@ -454,7 +794,7 @@ module Nokogiri
|
|
|
454
794
|
# Parse +string_or_io+ as a document fragment within the context of
|
|
455
795
|
# *this* node. Returns a XML::NodeSet containing the nodes parsed from
|
|
456
796
|
# +string_or_io+.
|
|
457
|
-
def parse
|
|
797
|
+
def parse(string_or_io, options = nil)
|
|
458
798
|
##
|
|
459
799
|
# When the current node is unparented and not an element node, use the
|
|
460
800
|
# document as the parsing context instead. Otherwise, the in-context
|
|
@@ -477,30 +817,34 @@ module Nokogiri
|
|
|
477
817
|
|
|
478
818
|
return Nokogiri::XML::NodeSet.new(document) if contents.empty?
|
|
479
819
|
|
|
480
|
-
|
|
481
|
-
#
|
|
820
|
+
# libxml2 does not obey the `recover` option after encountering errors during `in_context`
|
|
821
|
+
# parsing, and so this horrible hack is here to try to emulate recovery behavior.
|
|
822
|
+
#
|
|
823
|
+
# Unfortunately, this means we're no longer parsing "in context" and so namespaces that
|
|
824
|
+
# would have been inherited from the context node won't be handled correctly. This hack was
|
|
825
|
+
# written in 2010, and I regret it, because it's silently degrading functionality in a way
|
|
826
|
+
# that's not easily prevented (or even detected).
|
|
827
|
+
#
|
|
828
|
+
# I think preferable behavior would be to either:
|
|
829
|
+
#
|
|
830
|
+
# a. add an error noting that we "fell back" and pointing the user to turning off the `recover` option
|
|
831
|
+
# b. don't recover, but raise a sensible exception
|
|
832
|
+
#
|
|
833
|
+
# For context and background: https://github.com/sparklemotion/nokogiri/issues/313
|
|
834
|
+
# FIXME bug report: https://github.com/sparklemotion/nokogiri/issues/2092
|
|
482
835
|
error_count = document.errors.length
|
|
483
836
|
node_set = in_context(contents, options.to_i)
|
|
484
|
-
if node_set.empty?
|
|
485
|
-
|
|
486
|
-
|
|
837
|
+
if (node_set.empty? && (document.errors.length > error_count))
|
|
838
|
+
if options.recover?
|
|
839
|
+
fragment = Nokogiri::HTML::DocumentFragment.parse contents
|
|
840
|
+
node_set = fragment.children
|
|
841
|
+
else
|
|
842
|
+
raise document.errors[error_count]
|
|
843
|
+
end
|
|
487
844
|
end
|
|
488
845
|
node_set
|
|
489
846
|
end
|
|
490
847
|
|
|
491
|
-
####
|
|
492
|
-
# Set the Node's content to a Text node containing +string+. The string gets XML escaped, not interpreted as markup.
|
|
493
|
-
def content= string
|
|
494
|
-
self.native_content = encode_special_chars(string.to_s)
|
|
495
|
-
end
|
|
496
|
-
|
|
497
|
-
###
|
|
498
|
-
# Set the parent Node for this Node
|
|
499
|
-
def parent= parent_node
|
|
500
|
-
parent_node.add_child(self)
|
|
501
|
-
parent_node
|
|
502
|
-
end
|
|
503
|
-
|
|
504
848
|
###
|
|
505
849
|
# Returns a Hash of +{prefix => value}+ for all namespaces on this
|
|
506
850
|
# node and its ancestors.
|
|
@@ -582,6 +926,7 @@ module Nokogiri
|
|
|
582
926
|
def element?
|
|
583
927
|
type == ELEMENT_NODE
|
|
584
928
|
end
|
|
929
|
+
|
|
585
930
|
alias :elem? :element?
|
|
586
931
|
|
|
587
932
|
###
|
|
@@ -592,7 +937,7 @@ module Nokogiri
|
|
|
592
937
|
end
|
|
593
938
|
|
|
594
939
|
# Get the inner_html for this node's Node#children
|
|
595
|
-
def inner_html
|
|
940
|
+
def inner_html(*args)
|
|
596
941
|
children.map { |x| x.to_html(*args) }.join
|
|
597
942
|
end
|
|
598
943
|
|
|
@@ -600,13 +945,13 @@ module Nokogiri
|
|
|
600
945
|
def css_path
|
|
601
946
|
path.split(/\//).map { |part|
|
|
602
947
|
part.length == 0 ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
|
|
603
|
-
}.compact.join(
|
|
948
|
+
}.compact.join(" > ")
|
|
604
949
|
end
|
|
605
950
|
|
|
606
951
|
###
|
|
607
952
|
# Get a list of ancestor Node for this Node. If +selector+ is given,
|
|
608
953
|
# the ancestors must match +selector+
|
|
609
|
-
def ancestors
|
|
954
|
+
def ancestors(selector = nil)
|
|
610
955
|
return NodeSet.new(document) unless respond_to?(:parent)
|
|
611
956
|
return NodeSet.new(document) unless parent
|
|
612
957
|
|
|
@@ -627,57 +972,38 @@ module Nokogiri
|
|
|
627
972
|
})
|
|
628
973
|
end
|
|
629
974
|
|
|
630
|
-
###
|
|
631
|
-
# Adds a default namespace supplied as a string +url+ href, to self.
|
|
632
|
-
# The consequence is as an xmlns attribute with supplied argument were
|
|
633
|
-
# present in parsed XML. A default namespace set with this method will
|
|
634
|
-
# now show up in #attributes, but when this node is serialized to XML an
|
|
635
|
-
# "xmlns" attribute will appear. See also #namespace and #namespace=
|
|
636
|
-
def default_namespace= url
|
|
637
|
-
add_namespace_definition(nil, url)
|
|
638
|
-
end
|
|
639
|
-
alias :add_namespace :add_namespace_definition
|
|
640
|
-
|
|
641
|
-
###
|
|
642
|
-
# Set the default namespace on this node (as would be defined with an
|
|
643
|
-
# "xmlns=" attribute in XML source), as a Namespace object +ns+. Note that
|
|
644
|
-
# a Namespace added this way will NOT be serialized as an xmlns attribute
|
|
645
|
-
# for this node. You probably want #default_namespace= instead, or perhaps
|
|
646
|
-
# #add_namespace_definition with a nil prefix argument.
|
|
647
|
-
def namespace= ns
|
|
648
|
-
return set_namespace(ns) unless ns
|
|
649
|
-
|
|
650
|
-
unless Nokogiri::XML::Namespace === ns
|
|
651
|
-
raise TypeError, "#{ns.class} can't be coerced into Nokogiri::XML::Namespace"
|
|
652
|
-
end
|
|
653
|
-
if ns.document != document
|
|
654
|
-
raise ArgumentError, 'namespace must be declared on the same document'
|
|
655
|
-
end
|
|
656
|
-
|
|
657
|
-
set_namespace ns
|
|
658
|
-
end
|
|
659
|
-
|
|
660
975
|
####
|
|
661
976
|
# Yields self and all children to +block+ recursively.
|
|
662
|
-
def traverse
|
|
663
|
-
children.each{|j| j.traverse(&block) }
|
|
977
|
+
def traverse(&block)
|
|
978
|
+
children.each { |j| j.traverse(&block) }
|
|
664
979
|
block.call(self)
|
|
665
980
|
end
|
|
666
981
|
|
|
667
982
|
###
|
|
668
983
|
# Accept a visitor. This method calls "visit" on +visitor+ with self.
|
|
669
|
-
def accept
|
|
984
|
+
def accept(visitor)
|
|
670
985
|
visitor.visit(self)
|
|
671
986
|
end
|
|
672
987
|
|
|
673
988
|
###
|
|
674
989
|
# Test to see if this Node is equal to +other+
|
|
675
|
-
def ==
|
|
990
|
+
def ==(other)
|
|
676
991
|
return false unless other
|
|
677
992
|
return false unless other.respond_to?(:pointer_id)
|
|
678
993
|
pointer_id == other.pointer_id
|
|
679
994
|
end
|
|
680
995
|
|
|
996
|
+
###
|
|
997
|
+
# Compare two Node objects with respect to their Document. Nodes from
|
|
998
|
+
# different documents cannot be compared.
|
|
999
|
+
def <=>(other)
|
|
1000
|
+
return nil unless other.is_a?(Nokogiri::XML::Node)
|
|
1001
|
+
return nil unless document == other.document
|
|
1002
|
+
compare other
|
|
1003
|
+
end
|
|
1004
|
+
|
|
1005
|
+
# @!group Serialization and Generating Output
|
|
1006
|
+
|
|
681
1007
|
###
|
|
682
1008
|
# Serialize Node using +options+. Save options can also be set using a
|
|
683
1009
|
# block. See SaveOptions.
|
|
@@ -692,17 +1018,17 @@ module Nokogiri
|
|
|
692
1018
|
# config.format.as_xml
|
|
693
1019
|
# end
|
|
694
1020
|
#
|
|
695
|
-
def serialize
|
|
1021
|
+
def serialize(*args, &block)
|
|
696
1022
|
options = args.first.is_a?(Hash) ? args.shift : {
|
|
697
|
-
:encoding
|
|
698
|
-
:save_with
|
|
1023
|
+
:encoding => args[0],
|
|
1024
|
+
:save_with => args[1],
|
|
699
1025
|
}
|
|
700
1026
|
|
|
701
1027
|
encoding = options[:encoding] || document.encoding
|
|
702
1028
|
options[:encoding] = encoding
|
|
703
1029
|
|
|
704
1030
|
outstring = String.new
|
|
705
|
-
outstring.force_encoding(Encoding.find(encoding ||
|
|
1031
|
+
outstring.force_encoding(Encoding.find(encoding || "utf-8"))
|
|
706
1032
|
io = StringIO.new(outstring)
|
|
707
1033
|
write_to io, options, &block
|
|
708
1034
|
io.string
|
|
@@ -715,7 +1041,7 @@ module Nokogiri
|
|
|
715
1041
|
#
|
|
716
1042
|
# See Node#write_to for a list of +options+. For formatted output,
|
|
717
1043
|
# use Node#to_xhtml instead.
|
|
718
|
-
def to_html
|
|
1044
|
+
def to_html(options = {})
|
|
719
1045
|
to_format SaveOptions::DEFAULT_HTML, options
|
|
720
1046
|
end
|
|
721
1047
|
|
|
@@ -725,7 +1051,7 @@ module Nokogiri
|
|
|
725
1051
|
# doc.to_xml(:indent => 5, :encoding => 'UTF-8')
|
|
726
1052
|
#
|
|
727
1053
|
# See Node#write_to for a list of +options+
|
|
728
|
-
def to_xml
|
|
1054
|
+
def to_xml(options = {})
|
|
729
1055
|
options[:save_with] ||= SaveOptions::DEFAULT_XML
|
|
730
1056
|
serialize(options)
|
|
731
1057
|
end
|
|
@@ -736,7 +1062,7 @@ module Nokogiri
|
|
|
736
1062
|
# doc.to_xhtml(:indent => 5, :encoding => 'UTF-8')
|
|
737
1063
|
#
|
|
738
1064
|
# See Node#write_to for a list of +options+
|
|
739
|
-
def to_xhtml
|
|
1065
|
+
def to_xhtml(options = {})
|
|
740
1066
|
to_format SaveOptions::DEFAULT_XHTML, options
|
|
741
1067
|
end
|
|
742
1068
|
|
|
@@ -757,22 +1083,22 @@ module Nokogiri
|
|
|
757
1083
|
#
|
|
758
1084
|
# node.write_to(io, :indent_text => '-', :indent => 2)
|
|
759
1085
|
#
|
|
760
|
-
def write_to
|
|
761
|
-
options
|
|
762
|
-
encoding
|
|
1086
|
+
def write_to(io, *options)
|
|
1087
|
+
options = options.first.is_a?(Hash) ? options.shift : {}
|
|
1088
|
+
encoding = options[:encoding] || options[0]
|
|
763
1089
|
if Nokogiri.jruby?
|
|
764
|
-
save_options
|
|
765
|
-
indent_times
|
|
1090
|
+
save_options = options[:save_with] || options[1]
|
|
1091
|
+
indent_times = options[:indent] || 0
|
|
766
1092
|
else
|
|
767
|
-
save_options
|
|
768
|
-
indent_times
|
|
1093
|
+
save_options = options[:save_with] || options[1] || SaveOptions::FORMAT
|
|
1094
|
+
indent_times = options[:indent] || 2
|
|
769
1095
|
end
|
|
770
|
-
indent_text
|
|
1096
|
+
indent_text = options[:indent_text] || " "
|
|
771
1097
|
|
|
772
1098
|
# Any string times 0 returns an empty string. Therefore, use the same
|
|
773
1099
|
# string instead of generating a new empty string for every node with
|
|
774
1100
|
# zero indentation.
|
|
775
|
-
indentation = indent_times.zero? ?
|
|
1101
|
+
indentation = indent_times.zero? ? "" : (indent_text * indent_times)
|
|
776
1102
|
|
|
777
1103
|
config = SaveOptions.new(save_options.to_i)
|
|
778
1104
|
yield config if block_given?
|
|
@@ -784,7 +1110,7 @@ module Nokogiri
|
|
|
784
1110
|
# Write Node as HTML to +io+ with +options+
|
|
785
1111
|
#
|
|
786
1112
|
# See Node#write_to for a list of +options+
|
|
787
|
-
def write_html_to
|
|
1113
|
+
def write_html_to(io, options = {})
|
|
788
1114
|
write_format_to SaveOptions::DEFAULT_HTML, io, options
|
|
789
1115
|
end
|
|
790
1116
|
|
|
@@ -792,7 +1118,7 @@ module Nokogiri
|
|
|
792
1118
|
# Write Node as XHTML to +io+ with +options+
|
|
793
1119
|
#
|
|
794
1120
|
# See Node#write_to for a list of +options+
|
|
795
|
-
def write_xhtml_to
|
|
1121
|
+
def write_xhtml_to(io, options = {})
|
|
796
1122
|
write_format_to SaveOptions::DEFAULT_XHTML, io, options
|
|
797
1123
|
end
|
|
798
1124
|
|
|
@@ -802,52 +1128,66 @@ module Nokogiri
|
|
|
802
1128
|
# doc.write_xml_to io, :encoding => 'UTF-8'
|
|
803
1129
|
#
|
|
804
1130
|
# See Node#write_to for a list of options
|
|
805
|
-
def write_xml_to
|
|
1131
|
+
def write_xml_to(io, options = {})
|
|
806
1132
|
options[:save_with] ||= SaveOptions::DEFAULT_XML
|
|
807
1133
|
write_to io, options
|
|
808
1134
|
end
|
|
809
1135
|
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
compare other
|
|
1136
|
+
def canonicalize(mode = XML::XML_C14N_1_0, inclusive_namespaces = nil, with_comments = false)
|
|
1137
|
+
c14n_root = self
|
|
1138
|
+
document.canonicalize(mode, inclusive_namespaces, with_comments) do |node, parent|
|
|
1139
|
+
tn = node.is_a?(XML::Node) ? node : parent
|
|
1140
|
+
tn == c14n_root || tn.ancestors.include?(c14n_root)
|
|
1141
|
+
end
|
|
817
1142
|
end
|
|
818
1143
|
|
|
819
|
-
|
|
820
|
-
# Do xinclude substitution on the subtree below node. If given a block, a
|
|
821
|
-
# Nokogiri::XML::ParseOptions object initialized from +options+, will be
|
|
822
|
-
# passed to it, allowing more convenient modification of the parser options.
|
|
823
|
-
def do_xinclude options = XML::ParseOptions::DEFAULT_XML
|
|
824
|
-
options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
|
|
1144
|
+
# @!endgroup
|
|
825
1145
|
|
|
826
|
-
|
|
827
|
-
yield options if block_given?
|
|
1146
|
+
protected
|
|
828
1147
|
|
|
829
|
-
|
|
830
|
-
|
|
1148
|
+
def coerce(data)
|
|
1149
|
+
case data
|
|
1150
|
+
when XML::NodeSet
|
|
1151
|
+
return data
|
|
1152
|
+
when XML::DocumentFragment
|
|
1153
|
+
return data.children
|
|
1154
|
+
when String
|
|
1155
|
+
return fragment(data).children
|
|
1156
|
+
when Document, XML::Attr
|
|
1157
|
+
# unacceptable
|
|
1158
|
+
when XML::Node
|
|
1159
|
+
return data
|
|
1160
|
+
end
|
|
1161
|
+
|
|
1162
|
+
raise ArgumentError, <<-EOERR
|
|
1163
|
+
Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
|
1164
|
+
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
|
|
1165
|
+
EOERR
|
|
831
1166
|
end
|
|
832
1167
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1168
|
+
private
|
|
1169
|
+
|
|
1170
|
+
def keywordify(keywords)
|
|
1171
|
+
case keywords
|
|
1172
|
+
when Enumerable
|
|
1173
|
+
return keywords
|
|
1174
|
+
when String
|
|
1175
|
+
return keywords.scan(/\S+/)
|
|
1176
|
+
else
|
|
1177
|
+
raise ArgumentError.new("Keyword attributes must be passed as either a String or an Enumerable, but received #{keywords.class}")
|
|
838
1178
|
end
|
|
839
1179
|
end
|
|
840
1180
|
|
|
841
|
-
|
|
1181
|
+
def add_sibling(next_or_previous, node_or_tags)
|
|
1182
|
+
raise("Cannot add sibling to a node with no parent") unless parent
|
|
842
1183
|
|
|
843
|
-
def add_sibling next_or_previous, node_or_tags
|
|
844
1184
|
impl = (next_or_previous == :next) ? :add_next_sibling_node : :add_previous_sibling_node
|
|
845
|
-
iter = (next_or_previous == :next) ? :reverse_each
|
|
1185
|
+
iter = (next_or_previous == :next) ? :reverse_each : :each
|
|
846
1186
|
|
|
847
|
-
node_or_tags = coerce
|
|
1187
|
+
node_or_tags = parent.coerce(node_or_tags)
|
|
848
1188
|
if node_or_tags.is_a?(XML::NodeSet)
|
|
849
1189
|
if text?
|
|
850
|
-
pivot = Nokogiri::XML::Node.new
|
|
1190
|
+
pivot = Nokogiri::XML::Node.new "dummy", document
|
|
851
1191
|
send impl, pivot
|
|
852
1192
|
else
|
|
853
1193
|
pivot = self
|
|
@@ -863,14 +1203,14 @@ module Nokogiri
|
|
|
863
1203
|
USING_LIBXML_WITH_BROKEN_SERIALIZATION = Nokogiri.uses_libxml?("~> 2.6.0").freeze
|
|
864
1204
|
private_constant :USING_LIBXML_WITH_BROKEN_SERIALIZATION
|
|
865
1205
|
|
|
866
|
-
def to_format
|
|
1206
|
+
def to_format(save_option, options)
|
|
867
1207
|
return dump_html if USING_LIBXML_WITH_BROKEN_SERIALIZATION
|
|
868
1208
|
|
|
869
1209
|
options[:save_with] = save_option unless options[:save_with]
|
|
870
1210
|
serialize(options)
|
|
871
1211
|
end
|
|
872
1212
|
|
|
873
|
-
def write_format_to
|
|
1213
|
+
def write_format_to(save_option, io, options)
|
|
874
1214
|
return (io << dump_html) if USING_LIBXML_WITH_BROKEN_SERIALIZATION
|
|
875
1215
|
|
|
876
1216
|
options[:save_with] ||= save_option
|
|
@@ -881,30 +1221,10 @@ module Nokogiri
|
|
|
881
1221
|
[:name, :namespace, :attribute_nodes, :children]
|
|
882
1222
|
end
|
|
883
1223
|
|
|
884
|
-
def coerce data # :nodoc:
|
|
885
|
-
case data
|
|
886
|
-
when XML::NodeSet
|
|
887
|
-
return data
|
|
888
|
-
when XML::DocumentFragment
|
|
889
|
-
return data.children
|
|
890
|
-
when String
|
|
891
|
-
return fragment(data).children
|
|
892
|
-
when Document, XML::Attr
|
|
893
|
-
# unacceptable
|
|
894
|
-
when XML::Node
|
|
895
|
-
return data
|
|
896
|
-
end
|
|
897
|
-
|
|
898
|
-
raise ArgumentError, <<-EOERR
|
|
899
|
-
Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
|
|
900
|
-
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
|
|
901
|
-
EOERR
|
|
902
|
-
end
|
|
903
|
-
|
|
904
1224
|
# @private
|
|
905
|
-
IMPLIED_XPATH_CONTEXTS = [
|
|
1225
|
+
IMPLIED_XPATH_CONTEXTS = [".//".freeze].freeze
|
|
906
1226
|
|
|
907
|
-
def add_child_node_and_reparent_attrs
|
|
1227
|
+
def add_child_node_and_reparent_attrs(node)
|
|
908
1228
|
add_child_node node
|
|
909
1229
|
node.attribute_nodes.find_all { |a| a.name =~ /:/ }.each do |attr_node|
|
|
910
1230
|
attr_node.remove
|