nokogiri 1.6.1-java → 1.6.2-java
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/.editorconfig +17 -0
- data/.travis.yml +6 -6
- data/CHANGELOG.ja.rdoc +61 -8
- data/CHANGELOG.rdoc +58 -3
- data/Gemfile +3 -3
- data/Manifest.txt +57 -1
- data/README.ja.rdoc +22 -17
- data/README.rdoc +23 -18
- data/ROADMAP.md +1 -2
- data/Rakefile +162 -58
- data/build_all +56 -31
- data/dependencies.yml +3 -3
- data/ext/java/nokogiri/NokogiriService.java +9 -5
- data/ext/java/nokogiri/XmlDocument.java +95 -54
- data/ext/java/nokogiri/XmlNode.java +93 -42
- data/ext/java/nokogiri/XmlReader.java +1 -1
- data/ext/java/nokogiri/XmlSaxParserContext.java +33 -0
- data/ext/java/nokogiri/XmlSchema.java +4 -2
- data/ext/java/nokogiri/XmlXpathContext.java +118 -76
- data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +20 -0
- data/ext/java/nokogiri/internals/NokogiriHandler.java +3 -10
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +40 -23
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +59 -54
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +1 -1
- data/ext/java/nokogiri/internals/ParserContext.java +1 -4
- data/ext/java/nokogiri/internals/SaveContextVisitor.java +6 -2
- data/ext/java/nokogiri/internals/c14n/AttrCompare.java +119 -0
- data/ext/java/nokogiri/internals/c14n/C14nHelper.java +159 -0
- data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +37 -0
- data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +93 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +252 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +639 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +38 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +38 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +368 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +295 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +40 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +44 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +44 -0
- data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +43 -0
- data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +630 -0
- data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +173 -0
- data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +76 -0
- data/ext/java/nokogiri/internals/c14n/Constants.java +42 -0
- data/ext/java/nokogiri/internals/c14n/ElementProxy.java +293 -0
- data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +93 -0
- data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +79 -0
- data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +165 -0
- data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +76 -0
- data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +402 -0
- data/ext/java/nokogiri/internals/c14n/NodeFilter.java +51 -0
- data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +179 -0
- data/ext/java/nokogiri/internals/c14n/XMLUtils.java +507 -0
- data/ext/nokogiri/extconf.rb +429 -128
- data/ext/nokogiri/html_document.c +2 -2
- data/ext/nokogiri/nokogiri.c +6 -1
- data/ext/nokogiri/xml_document.c +5 -4
- data/ext/nokogiri/xml_node.c +76 -7
- data/ext/nokogiri/xml_reader.c +1 -1
- data/ext/nokogiri/xml_sax_parser_context.c +40 -0
- data/ext/nokogiri/xml_syntax_error.c +10 -5
- data/ext/nokogiri/xml_syntax_error.h +1 -1
- data/ext/nokogiri/xml_xpath_context.c +2 -14
- data/ext/nokogiri/xslt_stylesheet.c +1 -1
- data/lib/nokogiri.rb +31 -22
- data/lib/nokogiri/css/node.rb +0 -50
- data/lib/nokogiri/css/parser.rb +213 -218
- data/lib/nokogiri/css/parser.y +21 -30
- data/lib/nokogiri/css/xpath_visitor.rb +62 -14
- data/lib/nokogiri/html/document.rb +97 -18
- data/lib/nokogiri/html/sax/parser.rb +2 -2
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/builder.rb +1 -1
- data/lib/nokogiri/xml/document.rb +2 -2
- data/lib/nokogiri/xml/dtd.rb +10 -0
- data/lib/nokogiri/xml/node.rb +26 -1
- data/lib/nokogiri/xml/sax/parser.rb +1 -1
- data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
- data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
- data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
- data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
- data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
- data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
- data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
- data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
- data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
- data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
- data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
- data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
- data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
- data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
- data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
- data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
- data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
- data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
- data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
- data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
- data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
- data/suppressions/README.txt +1 -0
- data/suppressions/nokogiri_ree-1.8.7.358.supp +61 -0
- data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
- data/suppressions/nokogiri_ruby-1.9.2.320.supp +28 -0
- data/suppressions/nokogiri_ruby-1.9.3.327.supp +28 -0
- data/test/css/test_nthiness.rb +65 -2
- data/test/css/test_parser.rb +27 -10
- data/test/css/test_tokenizer.rb +1 -1
- data/test/css/test_xpath_visitor.rb +6 -1
- data/test/files/atom.xml +344 -0
- data/test/files/shift_jis_no_charset.html +9 -0
- data/test/helper.rb +10 -0
- data/test/html/test_document.rb +74 -7
- data/test/html/test_document_encoding.rb +10 -0
- data/test/html/test_document_fragment.rb +9 -3
- data/test/namespaces/test_namespaces_aliased_default.rb +24 -0
- data/test/namespaces/test_namespaces_in_cloned_doc.rb +31 -0
- data/test/namespaces/test_namespaces_preservation.rb +31 -0
- data/test/test_nokogiri.rb +6 -0
- data/test/test_reader.rb +7 -4
- data/test/test_xslt_transforms.rb +25 -0
- data/test/xml/sax/test_parser.rb +16 -0
- data/test/xml/sax/test_parser_context.rb +9 -0
- data/test/xml/test_builder.rb +9 -0
- data/test/xml/test_c14n.rb +12 -2
- data/test/xml/test_document.rb +66 -0
- data/test/xml/test_document_fragment.rb +5 -0
- data/test/xml/test_dtd.rb +84 -0
- data/test/xml/test_entity_reference.rb +3 -3
- data/test/xml/test_node.rb +21 -3
- data/test/xml/test_node_attributes.rb +17 -0
- data/test/xml/test_schema.rb +26 -0
- data/test/xml/test_text.rb +15 -0
- data/test/xml/test_xpath.rb +87 -0
- data/test_all +3 -3
- metadata +119 -68
- data/tasks/cross_compile.rb +0 -134
data/lib/nokogiri/css/parser.y
CHANGED
@@ -28,17 +28,6 @@ rule
|
|
28
28
|
Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
|
29
29
|
end
|
30
30
|
}
|
31
|
-
| element_name hcap_1toN negation {
|
32
|
-
result = Node.new(:CONDITIONAL_SELECTOR,
|
33
|
-
[
|
34
|
-
val.first,
|
35
|
-
Node.new(:COMBINATOR, [val[1], val.last])
|
36
|
-
]
|
37
|
-
)
|
38
|
-
}
|
39
|
-
| element_name negation {
|
40
|
-
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
41
|
-
}
|
42
31
|
| function
|
43
32
|
| function pseudo {
|
44
33
|
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
@@ -46,14 +35,6 @@ rule
|
|
46
35
|
| function attrib {
|
47
36
|
result = Node.new(:CONDITIONAL_SELECTOR, val)
|
48
37
|
}
|
49
|
-
| hcap_1toN negation {
|
50
|
-
result = Node.new(:CONDITIONAL_SELECTOR,
|
51
|
-
[
|
52
|
-
Node.new(:ELEMENT_NAME, ['*']),
|
53
|
-
Node.new(:COMBINATOR, val)
|
54
|
-
]
|
55
|
-
)
|
56
|
-
}
|
57
38
|
| hcap_1toN {
|
58
39
|
result = Node.new(:CONDITIONAL_SELECTOR,
|
59
40
|
[Node.new(:ELEMENT_NAME, ['*']), val.first]
|
@@ -130,7 +111,7 @@ rule
|
|
130
111
|
| FUNCTION expr RPAREN {
|
131
112
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
132
113
|
}
|
133
|
-
| FUNCTION
|
114
|
+
| FUNCTION nth RPAREN {
|
134
115
|
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
|
135
116
|
}
|
136
117
|
| NOT expr RPAREN {
|
@@ -150,10 +131,10 @@ rule
|
|
150
131
|
{
|
151
132
|
if val[0] == 'even'
|
152
133
|
val = ["2","n","+","0"]
|
153
|
-
result = Node.new(:
|
134
|
+
result = Node.new(:NTH, val)
|
154
135
|
elsif val[0] == 'odd'
|
155
136
|
val = ["2","n","+","1"]
|
156
|
-
result = Node.new(:
|
137
|
+
result = Node.new(:NTH, val)
|
157
138
|
else
|
158
139
|
# This is not CSS standard. It allows us to support this:
|
159
140
|
# assert_xpath("//a[foo(., @href)]", @parser.parse('a:foo(@href)'))
|
@@ -163,11 +144,11 @@ rule
|
|
163
144
|
end
|
164
145
|
}
|
165
146
|
;
|
166
|
-
|
147
|
+
nth
|
167
148
|
: NUMBER IDENT PLUS NUMBER # 5n+3 -5n+3
|
168
149
|
{
|
169
150
|
if val[1] == 'n'
|
170
|
-
result = Node.new(:
|
151
|
+
result = Node.new(:NTH, val)
|
171
152
|
else
|
172
153
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
173
154
|
end
|
@@ -175,21 +156,27 @@ rule
|
|
175
156
|
| IDENT PLUS NUMBER { # n+3, -n+3
|
176
157
|
if val[0] == 'n'
|
177
158
|
val.unshift("1")
|
178
|
-
result = Node.new(:
|
159
|
+
result = Node.new(:NTH, val)
|
179
160
|
elsif val[0] == '-n'
|
180
161
|
val[0] = 'n'
|
181
162
|
val.unshift("-1")
|
182
|
-
result = Node.new(:
|
163
|
+
result = Node.new(:NTH, val)
|
183
164
|
else
|
184
165
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
185
166
|
end
|
186
167
|
}
|
187
|
-
| NUMBER IDENT
|
188
|
-
|
189
|
-
if
|
168
|
+
| NUMBER IDENT { # 5n, -5n, 10n-1
|
169
|
+
n = val[1]
|
170
|
+
if n[0, 2] == 'n-'
|
171
|
+
val[1] = 'n'
|
172
|
+
val << "-"
|
173
|
+
# b is contained in n as n is the string "n-b"
|
174
|
+
val << n[2, n.size]
|
175
|
+
result = Node.new(:NTH, val)
|
176
|
+
elsif n == 'n'
|
190
177
|
val << "+"
|
191
178
|
val << "0"
|
192
|
-
result = Node.new(:
|
179
|
+
result = Node.new(:NTH, val)
|
193
180
|
else
|
194
181
|
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
195
182
|
end
|
@@ -218,10 +205,14 @@ rule
|
|
218
205
|
| pseudo hcap_1toN {
|
219
206
|
result = Node.new(:COMBINATOR, val)
|
220
207
|
}
|
208
|
+
| negation hcap_1toN {
|
209
|
+
result = Node.new(:COMBINATOR, val)
|
210
|
+
}
|
221
211
|
| attribute_id
|
222
212
|
| class
|
223
213
|
| attrib
|
224
214
|
| pseudo
|
215
|
+
| negation
|
225
216
|
;
|
226
217
|
attribute_id
|
227
218
|
: HASH { result = Node.new(:ID, val) }
|
@@ -2,7 +2,7 @@ module Nokogiri
|
|
2
2
|
module CSS
|
3
3
|
class XPathVisitor # :nodoc:
|
4
4
|
def visit_function node
|
5
|
-
|
5
|
+
|
6
6
|
msg = :"visit_function_#{node.value.first.gsub(/[(]/, '')}"
|
7
7
|
return self.send(msg, node) if self.respond_to?(msg)
|
8
8
|
|
@@ -13,19 +13,31 @@ module Nokogiri
|
|
13
13
|
"self::#{node.value[1]}"
|
14
14
|
when /^eq\(/
|
15
15
|
"position() = #{node.value[1]}"
|
16
|
-
when /^(nth|nth-of-type
|
17
|
-
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :
|
18
|
-
|
16
|
+
when /^(nth|nth-of-type)\(/
|
17
|
+
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :NTH
|
18
|
+
nth(node.value[1])
|
19
19
|
else
|
20
20
|
"position() = #{node.value[1]}"
|
21
21
|
end
|
22
|
-
when /^
|
23
|
-
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :
|
24
|
-
|
22
|
+
when /^nth-child\(/
|
23
|
+
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :NTH
|
24
|
+
nth(node.value[1], :child => true)
|
25
|
+
else
|
26
|
+
"count(preceding-sibling::*) = #{node.value[1].to_i-1}"
|
27
|
+
end
|
28
|
+
when /^nth-last-of-type\(/
|
29
|
+
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :NTH
|
30
|
+
nth(node.value[1], :last => true)
|
25
31
|
else
|
26
32
|
index = node.value[1].to_i - 1
|
27
33
|
index == 0 ? "position() = last()" : "position() = last() - #{index}"
|
28
34
|
end
|
35
|
+
when /^nth-last-child\(/
|
36
|
+
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :NTH
|
37
|
+
nth(node.value[1], :last => true, :child => true)
|
38
|
+
else
|
39
|
+
"count(following-sibling::*) = #{node.value[1].to_i-1}"
|
40
|
+
end
|
29
41
|
when /^(first|first-of-type)\(/
|
30
42
|
"position() = 1"
|
31
43
|
when /^(last|last-of-type)\(/
|
@@ -105,10 +117,13 @@ module Nokogiri
|
|
105
117
|
return self.send(msg, node) if self.respond_to?(msg)
|
106
118
|
|
107
119
|
case node.value.first
|
108
|
-
when "first"
|
109
|
-
when "
|
120
|
+
when "first" then "position() = 1"
|
121
|
+
when "first-child" then "count(preceding-sibling::*) = 0"
|
122
|
+
when "last" then "position() = last()"
|
123
|
+
when "last-child" then "count(following-sibling::*) = 0"
|
110
124
|
when "first-of-type" then "position() = 1"
|
111
125
|
when "last-of-type" then "position() = last()"
|
126
|
+
when "only-child" then "count(preceding-sibling::*) = 0 and count(following-sibling::*) = 0"
|
112
127
|
when "only-of-type" then "last() = 1"
|
113
128
|
when "empty" then "not(node())"
|
114
129
|
when "parent" then "node()"
|
@@ -123,8 +138,15 @@ module Nokogiri
|
|
123
138
|
"contains(concat(' ', normalize-space(@class), ' '), ' #{node.value.first} ')"
|
124
139
|
end
|
125
140
|
|
141
|
+
def visit_combinator node
|
142
|
+
if is_of_type_pseudo_class?(node.value.last)
|
143
|
+
"#{node.value.first.accept(self) if node.value.first}][#{node.value.last.accept(self)}"
|
144
|
+
else
|
145
|
+
"#{node.value.first.accept(self) if node.value.first} and #{node.value.last.accept(self)}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
126
149
|
{
|
127
|
-
'combinator' => ' and ',
|
128
150
|
'direct_adjacent_selector' => "/following-sibling::*[1]/self::",
|
129
151
|
'following_selector' => "/following-sibling::",
|
130
152
|
'descendant_selector' => '//',
|
@@ -151,12 +173,15 @@ module Nokogiri
|
|
151
173
|
end
|
152
174
|
|
153
175
|
private
|
154
|
-
def
|
176
|
+
def nth node, options={}
|
155
177
|
raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
|
156
178
|
|
157
|
-
a = node.value
|
158
|
-
|
159
|
-
|
179
|
+
a, b = read_a_and_positive_b node.value
|
180
|
+
position = if options[:child]
|
181
|
+
options[:last] ? "(count(following-sibling::*) + 1)" : "(count(preceding-sibling::*) + 1)"
|
182
|
+
else
|
183
|
+
options[:last] ? "(last()-position()+1)" : "position()"
|
184
|
+
end
|
160
185
|
|
161
186
|
if (b == 0)
|
162
187
|
return "(#{position} mod #{a}) = 0"
|
@@ -166,6 +191,29 @@ module Nokogiri
|
|
166
191
|
end
|
167
192
|
end
|
168
193
|
|
194
|
+
def read_a_and_positive_b values
|
195
|
+
op = values[2]
|
196
|
+
if op == "+"
|
197
|
+
a = values[0].to_i
|
198
|
+
b = values[3].to_i
|
199
|
+
elsif op == "-"
|
200
|
+
a = values[0].to_i
|
201
|
+
b = a - (values[3].to_i % a)
|
202
|
+
else
|
203
|
+
raise ArgumentError, "expected an+b node to have either + or - as the operator, but is #{op.inspect}"
|
204
|
+
end
|
205
|
+
[a, b]
|
206
|
+
end
|
207
|
+
|
208
|
+
def is_of_type_pseudo_class? node
|
209
|
+
if node.type==:PSEUDO_CLASS
|
210
|
+
if node.value[0].is_a?(Nokogiri::CSS::Node) and node.value[0].type == :FUNCTION
|
211
|
+
node.value[0].value[0]
|
212
|
+
else
|
213
|
+
node.value[0]
|
214
|
+
end =~ /(nth|first|last|only)-of-type(\()?/
|
215
|
+
end
|
216
|
+
end
|
169
217
|
end
|
170
218
|
end
|
171
219
|
end
|
@@ -5,24 +5,59 @@ module Nokogiri
|
|
5
5
|
# Get the meta tag encoding for this document. If there is no meta tag,
|
6
6
|
# then nil is returned.
|
7
7
|
def meta_encoding
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
case
|
9
|
+
when meta = at('//meta[@charset]')
|
10
|
+
meta[:charset]
|
11
|
+
when meta = meta_content_type
|
12
|
+
meta['content'][/charset\s*=\s*([\w-]+)/i, 1]
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
16
|
###
|
14
|
-
# Set the meta tag encoding for this document.
|
15
|
-
#
|
17
|
+
# Set the meta tag encoding for this document.
|
18
|
+
#
|
19
|
+
# If an meta encoding tag is already present, its content is
|
20
|
+
# replaced with the given text.
|
21
|
+
#
|
22
|
+
# Otherwise, this method tries to create one at an appropriate
|
23
|
+
# place supplying head and/or html elements as necessary, which
|
24
|
+
# is inside a head element if any, and before any text node or
|
25
|
+
# content element (typically <body>) if any.
|
26
|
+
#
|
27
|
+
# The result when trying to set an encoding that is different
|
28
|
+
# from the document encoding is undefined.
|
29
|
+
#
|
30
|
+
# Beware in CRuby, that libxml2 automatically inserts a meta tag
|
31
|
+
# into a head element.
|
16
32
|
def meta_encoding= encoding
|
17
|
-
|
18
|
-
|
33
|
+
case
|
34
|
+
when meta = meta_content_type
|
35
|
+
meta['content'] = 'text/html; charset=%s' % encoding
|
36
|
+
encoding
|
37
|
+
when meta = at('//meta[@charset]')
|
38
|
+
meta['charset'] = encoding
|
39
|
+
else
|
40
|
+
meta = XML::Node.new('meta', self)
|
41
|
+
if dtd = internal_subset and dtd.html5_dtd?
|
42
|
+
meta['charset'] = encoding
|
43
|
+
else
|
44
|
+
meta['http-equiv'] = 'Content-Type'
|
45
|
+
meta['content'] = 'text/html; charset=%s' % encoding
|
46
|
+
end
|
47
|
+
|
48
|
+
case
|
49
|
+
when head = at('//head')
|
50
|
+
head.prepend_child(meta)
|
51
|
+
else
|
52
|
+
set_metadata_element(meta)
|
53
|
+
end
|
54
|
+
encoding
|
55
|
+
end
|
19
56
|
end
|
20
57
|
|
21
58
|
def meta_content_type
|
22
|
-
|
23
|
-
node['http-equiv'] =~ /\AContent-Type\z/i
|
24
|
-
!node['content'].nil? and
|
25
|
-
!node['content'].empty?
|
59
|
+
xpath('//meta[@http-equiv and boolean(@content)]').find { |node|
|
60
|
+
node['http-equiv'] =~ /\AContent-Type\z/i
|
26
61
|
}
|
27
62
|
end
|
28
63
|
private :meta_content_type
|
@@ -31,20 +66,64 @@ module Nokogiri
|
|
31
66
|
# Get the title string of this document. Return nil if there is
|
32
67
|
# no title tag.
|
33
68
|
def title
|
34
|
-
title = at('title') and title.inner_text
|
69
|
+
title = at('//title') and title.inner_text
|
35
70
|
end
|
36
71
|
|
37
72
|
###
|
38
|
-
# Set the title string of this document.
|
39
|
-
#
|
73
|
+
# Set the title string of this document.
|
74
|
+
#
|
75
|
+
# If a title element is already present, its content is replaced
|
76
|
+
# with the given text.
|
77
|
+
#
|
78
|
+
# Otherwise, this method tries to create one at an appropriate
|
79
|
+
# place supplying head and/or html elements as necessary, which
|
80
|
+
# is inside a head element if any, right after a meta
|
81
|
+
# encoding/charset tag if any, and before any text node or
|
82
|
+
# content element (typically <body>) if any.
|
40
83
|
def title=(text)
|
41
|
-
|
42
|
-
|
43
|
-
title =
|
84
|
+
tnode = XML::Text.new(text, self)
|
85
|
+
if title = at('//title')
|
86
|
+
title.children = tnode
|
87
|
+
return text
|
88
|
+
end
|
89
|
+
|
90
|
+
title = XML::Node.new('title', self) << tnode
|
91
|
+
case
|
92
|
+
when head = at('//head')
|
44
93
|
head << title
|
94
|
+
when meta = at('//meta[@charset]') || meta_content_type
|
95
|
+
# better put after charset declaration
|
96
|
+
meta.add_next_sibling(title)
|
97
|
+
else
|
98
|
+
set_metadata_element(title)
|
99
|
+
end
|
100
|
+
text
|
101
|
+
end
|
102
|
+
|
103
|
+
def set_metadata_element(element)
|
104
|
+
case
|
105
|
+
when head = at('//head')
|
106
|
+
head << element
|
107
|
+
when html = at('//html')
|
108
|
+
head = html.prepend_child(XML::Node.new('head', self))
|
109
|
+
head.prepend_child(element)
|
110
|
+
when first = children.find { |node|
|
111
|
+
case node
|
112
|
+
when XML::Element, XML::Text
|
113
|
+
true
|
114
|
+
end
|
115
|
+
}
|
116
|
+
# We reach here only if the underlying document model
|
117
|
+
# allows <html>/<head> elements to be omitted and does not
|
118
|
+
# automatically supply them.
|
119
|
+
first.add_previous_sibling(element)
|
120
|
+
else
|
121
|
+
html = add_child(XML::Node.new('html', self))
|
122
|
+
head = html.add_child(XML::Node.new('head', self))
|
123
|
+
head.prepend_child(element)
|
45
124
|
end
|
46
|
-
title.children = XML::Text.new(text, self)
|
47
125
|
end
|
126
|
+
private :set_metadata_element
|
48
127
|
|
49
128
|
####
|
50
129
|
# Serialize Node using +options+. Save options can also be set using a
|
@@ -22,7 +22,7 @@ module Nokogiri
|
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# parser = Nokogiri::HTML::SAX::Parser.new(MyDoc.new)
|
25
|
-
# parser.parse(File.read(ARGV[0], 'rb'))
|
25
|
+
# parser.parse(File.read(ARGV[0], mode: 'rb'))
|
26
26
|
#
|
27
27
|
# For more information on SAX parsers, see Nokogiri::XML::SAX
|
28
28
|
class Parser < Nokogiri::XML::SAX::Parser
|
@@ -40,7 +40,7 @@ module Nokogiri
|
|
40
40
|
# Parse a file with +filename+
|
41
41
|
def parse_file filename, encoding = 'UTF-8'
|
42
42
|
raise ArgumentError unless filename
|
43
|
-
raise Errno::ENOENT unless File.
|
43
|
+
raise Errno::ENOENT unless File.exist?(filename)
|
44
44
|
raise Errno::EISDIR if File.directory?(filename)
|
45
45
|
ctx = ParserContext.file(filename, encoding)
|
46
46
|
yield ctx if block_given?
|
data/lib/nokogiri/nokogiri.jar
CHANGED
Binary file
|
data/lib/nokogiri/version.rb
CHANGED
data/lib/nokogiri/xml/builder.rb
CHANGED
@@ -45,7 +45,7 @@ module Nokogiri
|
|
45
45
|
# Give the options to the user
|
46
46
|
yield options if block_given?
|
47
47
|
|
48
|
-
return new if empty_doc?(string_or_io)
|
48
|
+
return new if !options.strict? && empty_doc?(string_or_io)
|
49
49
|
|
50
50
|
doc = if string_or_io.respond_to?(:read)
|
51
51
|
url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
|
@@ -233,7 +233,7 @@ module Nokogiri
|
|
233
233
|
undef_method :namespace_definitions, :line, :add_namespace
|
234
234
|
|
235
235
|
def add_child node_or_tags
|
236
|
-
raise "Document already has a root node" if root
|
236
|
+
raise "Document already has a root node" if root && root.name != 'nokogiri_text_wrapper'
|
237
237
|
node_or_tags = coerce(node_or_tags)
|
238
238
|
if node_or_tags.is_a?(XML::NodeSet)
|
239
239
|
raise "Document cannot have multiple root nodes" if node_or_tags.size > 1
|
data/lib/nokogiri/xml/dtd.rb
CHANGED
@@ -17,6 +17,16 @@ module Nokogiri
|
|
17
17
|
block.call([key, value])
|
18
18
|
}
|
19
19
|
end
|
20
|
+
|
21
|
+
def html_dtd?
|
22
|
+
name.casecmp('html').zero?
|
23
|
+
end
|
24
|
+
|
25
|
+
def html5_dtd?
|
26
|
+
html_dtd? &&
|
27
|
+
external_id.nil? &&
|
28
|
+
(system_id.nil? || system_id == 'about:legacy-compat')
|
29
|
+
end
|
20
30
|
end
|
21
31
|
end
|
22
32
|
end
|