nokogiri 1.5.0.beta.2 → 1.5.0.beta.3
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.
- data/CHANGELOG.ja.rdoc +63 -0
- data/CHANGELOG.rdoc +44 -1
- data/Manifest.txt +3 -3
- data/README.ja.rdoc +4 -4
- data/README.rdoc +4 -4
- data/Rakefile +3 -0
- data/bin/nokogiri +6 -1
- data/ext/java/nokogiri/EncodingHandler.java +32 -0
- data/ext/java/nokogiri/HtmlDocument.java +36 -0
- data/ext/java/nokogiri/HtmlElementDescription.java +34 -0
- data/ext/java/nokogiri/HtmlEntityLookup.java +34 -0
- data/ext/java/nokogiri/HtmlSaxParserContext.java +41 -3
- data/ext/java/nokogiri/NokogiriService.java +109 -13
- data/ext/java/nokogiri/XmlAttr.java +40 -4
- data/ext/java/nokogiri/XmlAttributeDecl.java +32 -0
- data/ext/java/nokogiri/XmlCdata.java +41 -2
- data/ext/java/nokogiri/XmlComment.java +38 -1
- data/ext/java/nokogiri/XmlDocument.java +56 -11
- data/ext/java/nokogiri/XmlDocumentFragment.java +39 -30
- data/ext/java/nokogiri/XmlDtd.java +37 -0
- data/ext/java/nokogiri/XmlElement.java +51 -2
- data/ext/java/nokogiri/XmlElementContent.java +32 -0
- data/ext/java/nokogiri/XmlElementDecl.java +32 -0
- data/ext/java/nokogiri/XmlEntityDecl.java +32 -0
- data/ext/java/nokogiri/XmlEntityReference.java +35 -2
- data/ext/java/nokogiri/XmlNamespace.java +55 -5
- data/ext/java/nokogiri/XmlNode.java +129 -136
- data/ext/java/nokogiri/XmlNodeSet.java +36 -0
- data/ext/java/nokogiri/XmlProcessingInstruction.java +34 -1
- data/ext/java/nokogiri/XmlReader.java +36 -0
- data/ext/java/nokogiri/XmlRelaxng.java +34 -1
- data/ext/java/nokogiri/XmlSaxParserContext.java +52 -7
- data/ext/java/nokogiri/XmlSaxPushParser.java +36 -0
- data/ext/java/nokogiri/XmlSchema.java +34 -1
- data/ext/java/nokogiri/XmlSyntaxError.java +48 -18
- data/ext/java/nokogiri/XmlText.java +45 -6
- data/ext/java/nokogiri/XmlXpathContext.java +45 -0
- data/ext/java/nokogiri/XsltStylesheet.java +58 -3
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +50 -26
- data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +35 -1
- data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +51 -13
- data/ext/java/nokogiri/internals/NokogiriHandler.java +70 -21
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +95 -38
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +37 -3
- data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +39 -1
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +43 -7
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +77 -10
- data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +49 -20
- data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +34 -2
- data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -1
- data/ext/java/nokogiri/internals/ParserContext.java +32 -0
- data/ext/java/nokogiri/internals/PushInputStream.java +33 -3
- data/ext/java/nokogiri/internals/ReaderNode.java +50 -8
- data/ext/java/nokogiri/internals/SaveContext.java +35 -2
- data/ext/java/nokogiri/internals/SchemaErrorHandler.java +34 -1
- data/ext/java/nokogiri/internals/XmlDeclHandler.java +32 -0
- data/ext/java/nokogiri/internals/XmlDomParser.java +32 -0
- data/ext/java/nokogiri/internals/XmlDomParserContext.java +43 -11
- data/ext/java/nokogiri/internals/XmlSaxParser.java +32 -0
- data/ext/java/nokogiri/internals/XsltExtensionFunction.java +72 -0
- data/ext/nokogiri/depend +358 -32
- data/ext/nokogiri/extconf.rb +1 -3
- data/ext/nokogiri/nokogiri.c +2 -0
- data/ext/nokogiri/nokogiri.h +7 -0
- data/ext/nokogiri/xml_dtd.c +2 -2
- data/ext/nokogiri/xml_io.c +2 -2
- data/ext/nokogiri/xml_node.c +31 -6
- data/ext/nokogiri/xml_node_set.c +1 -1
- data/ext/nokogiri/xml_sax_parser.c +1 -1
- data/ext/nokogiri/xml_sax_parser_context.c +40 -0
- data/ext/nokogiri/xml_xpath_context.c +33 -2
- data/ext/nokogiri/xslt_stylesheet.c +122 -6
- data/lib/nokogiri.rb +12 -5
- data/lib/nokogiri/css/generated_tokenizer.rb +1 -2
- data/lib/nokogiri/css/xpath_visitor.rb +15 -7
- data/lib/nokogiri/decorators/slop.rb +5 -3
- data/lib/nokogiri/html/document.rb +3 -3
- data/lib/nokogiri/html/document_fragment.rb +19 -17
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/document.rb +26 -1
- data/lib/nokogiri/xml/document_fragment.rb +2 -2
- data/lib/nokogiri/xml/dtd.rb +11 -0
- data/lib/nokogiri/xml/node.rb +156 -45
- data/lib/nokogiri/xml/node_set.rb +2 -2
- data/lib/nokogiri/xml/reader.rb +36 -0
- data/lib/nokogiri/xml/sax/document.rb +4 -2
- data/lib/nokogiri/xslt.rb +9 -5
- data/lib/nokogiri/xslt/stylesheet.rb +1 -1
- data/tasks/cross_compile.rb +27 -8
- data/test/css/test_parser.rb +29 -18
- data/test/decorators/test_slop.rb +16 -0
- data/test/html/test_document_fragment.rb +46 -3
- data/test/html/test_node.rb +9 -0
- data/test/xml/sax/test_parser.rb +11 -3
- data/test/xml/sax/test_parser_context.rb +50 -0
- data/test/xml/sax/test_push_parser.rb +18 -1
- data/test/xml/test_document_fragment.rb +15 -8
- data/test/xml/test_dtd.rb +15 -0
- data/test/xml/test_node.rb +31 -2
- data/test/xml/test_node_reparenting.rb +59 -31
- data/test/xml/test_node_set.rb +13 -0
- data/test/xml/test_xpath.rb +32 -0
- data/test/xslt/test_custom_functions.rb +94 -0
- metadata +83 -81
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/spec/helper.rb +0 -3
- data/spec/xml/reader_spec.rb +0 -307
@@ -38,7 +38,24 @@ module Nokogiri
|
|
38
38
|
<p id="asdfasdf">
|
39
39
|
eoxml
|
40
40
|
|
41
|
-
assert_equal [["p", ["id", "asdfasdf"]]],
|
41
|
+
assert_equal [["p", [["id", "asdfasdf"]]]],
|
42
|
+
@parser.document.start_elements
|
43
|
+
|
44
|
+
@parser.<<(<<-eoxml)
|
45
|
+
<!-- This is a comment -->
|
46
|
+
Paragraph 1
|
47
|
+
</p>
|
48
|
+
eoxml
|
49
|
+
assert_equal [' This is a comment '], @parser.document.comments
|
50
|
+
@parser.finish
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_start_element_with_namespaces
|
54
|
+
@parser.<<(<<-eoxml)
|
55
|
+
<p xmlns:foo="http://foo.example.com/">
|
56
|
+
eoxml
|
57
|
+
|
58
|
+
assert_equal [["p", [["xmlns:foo", "http://foo.example.com/"]]]],
|
42
59
|
@parser.document.start_elements
|
43
60
|
|
44
61
|
@parser.<<(<<-eoxml)
|
@@ -100,13 +100,13 @@ module Nokogiri
|
|
100
100
|
def test_xml_fragment_with_leading_whitespace
|
101
101
|
doc = " <div>b</div> "
|
102
102
|
fragment = Nokogiri::XML::Document.new.fragment(doc)
|
103
|
-
assert_equal "<div>b</div>", fragment.to_s
|
103
|
+
assert_equal " <div>b</div> ", fragment.to_s
|
104
104
|
end
|
105
105
|
|
106
106
|
def test_xml_fragment_with_leading_whitespace_and_newline
|
107
107
|
doc = " \n<div>b</div> "
|
108
108
|
fragment = Nokogiri::XML::Document.new.fragment(doc)
|
109
|
-
assert_equal "<div>b</div>", fragment.to_s
|
109
|
+
assert_equal " \n<div>b</div> ", fragment.to_s
|
110
110
|
end
|
111
111
|
|
112
112
|
def test_fragment_children_search
|
@@ -147,12 +147,7 @@ module Nokogiri
|
|
147
147
|
|
148
148
|
frag = doc.fragment "<bar:newnode></bar:newnode>"
|
149
149
|
assert frag.children.first.namespace
|
150
|
-
|
151
|
-
assert_equal ns, frag.children.first.namespace
|
152
|
-
else
|
153
|
-
assert_equal ns.href, frag.children.first.namespace.href
|
154
|
-
assert_equal ns.prefix, frag.children.first.namespace.prefix
|
155
|
-
end
|
150
|
+
assert_equal ns, frag.children.first.namespace
|
156
151
|
end
|
157
152
|
|
158
153
|
def test_fragment_invalid_namespace_is_silently_ignored
|
@@ -180,6 +175,18 @@ module Nokogiri
|
|
180
175
|
end
|
181
176
|
assert fragment.children.respond_to?(:awesome!), fragment.children.class
|
182
177
|
end
|
178
|
+
|
179
|
+
def test_for_libxml_in_context_fragment_parsing_bug_workaround
|
180
|
+
10.times do
|
181
|
+
begin
|
182
|
+
fragment = Nokogiri::XML.fragment("<div></div>")
|
183
|
+
parent = fragment.children.first
|
184
|
+
child = parent.parse("<h1></h1>").first
|
185
|
+
parent.add_child child
|
186
|
+
end
|
187
|
+
GC.start
|
188
|
+
end
|
189
|
+
end
|
183
190
|
end
|
184
191
|
end
|
185
192
|
end
|
data/test/xml/test_dtd.rb
CHANGED
@@ -29,11 +29,26 @@ module Nokogiri
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_empty_attributes
|
33
|
+
dtd = Nokogiri::HTML("<html></html>").internal_subset
|
34
|
+
assert_equal Hash.new, dtd.attributes
|
35
|
+
end
|
36
|
+
|
32
37
|
def test_attributes
|
33
38
|
assert_equal ['width'], @dtd.attributes.keys
|
34
39
|
assert_equal '0', @dtd.attributes['width'].default
|
35
40
|
end
|
36
41
|
|
42
|
+
def test_keys
|
43
|
+
assert_equal ['width'], @dtd.keys
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_each
|
47
|
+
hash = {}
|
48
|
+
@dtd.each { |key, value| hash[key] = value }
|
49
|
+
assert_equal @dtd.attributes, hash
|
50
|
+
end
|
51
|
+
|
37
52
|
def test_namespace
|
38
53
|
assert_raise NoMethodError do
|
39
54
|
@dtd.namespace
|
data/test/xml/test_node.rb
CHANGED
@@ -82,18 +82,47 @@ module Nokogiri
|
|
82
82
|
assert_equal 0, list.length
|
83
83
|
end
|
84
84
|
|
85
|
+
def test_parse_config_option
|
86
|
+
node = @xml.root
|
87
|
+
options = nil
|
88
|
+
node.parse("<item></item>") do |config|
|
89
|
+
options = config
|
90
|
+
end
|
91
|
+
assert_equal Nokogiri::XML::ParseOptions::DEFAULT_XML, options.to_i
|
92
|
+
end
|
93
|
+
|
85
94
|
# descriptive, not prescriptive.
|
86
95
|
def test_parse_invalid_html_markup_results_in_empty_nodeset
|
87
96
|
doc = Nokogiri::HTML("<html></html>")
|
88
97
|
nodeset = doc.root.parse "<div><div>a</div><snippet>b</snippet></div>"
|
89
98
|
assert_equal 1, doc.errors.length # "Tag snippet invalid"
|
99
|
+
assert_equal 1, nodeset.length
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_node_context_parsing_of_malformed_html_fragment_with_recover_is_corrected
|
103
|
+
doc = HTML.parse "<html><body><div></div></body></html>"
|
104
|
+
context_node = doc.at_css "div"
|
105
|
+
nodeset = context_node.parse("<div </div>") do |options|
|
106
|
+
options.recover
|
107
|
+
end
|
108
|
+
assert_equal "<div></div>", nodeset.to_s
|
109
|
+
assert_equal 1, doc.errors.length
|
110
|
+
assert_equal 1, nodeset.length
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_node_context_parsing_of_malformed_html_fragment_without_recover_is_not_corrected
|
114
|
+
doc = HTML.parse "<html><body><div></div></body></html>"
|
115
|
+
context_node = doc.at_css "div"
|
116
|
+
nodeset = context_node.parse("<div </div>") do |options|
|
117
|
+
options.strict
|
118
|
+
end
|
119
|
+
assert_equal 1, doc.errors.length
|
90
120
|
assert_equal 0, nodeset.length
|
91
121
|
end
|
92
122
|
|
93
123
|
def test_parse_error_list
|
94
124
|
error_count = @xml.errors.length
|
95
|
-
|
96
|
-
assert_equal 0, list.length
|
125
|
+
@xml.root.parse('<hello>')
|
97
126
|
assert(error_count < @xml.errors.length, "errors should have increased")
|
98
127
|
end
|
99
128
|
|
@@ -50,21 +50,22 @@ module Nokogiri
|
|
50
50
|
# end
|
51
51
|
|
52
52
|
{
|
53
|
-
:add_child => {:target => "/root/a1", :
|
54
|
-
:<< => {:target => "/root/a1", :
|
53
|
+
:add_child => {:target => "/root/a1", :returns_self => false, :children_tags => %w[text b1 b2]},
|
54
|
+
:<< => {:target => "/root/a1", :returns_self => false, :children_tags => %w[text b1 b2]},
|
55
55
|
|
56
|
-
:replace => {:target => "/root/a1/node()", :
|
57
|
-
:swap => {:target => "/root/a1/node()", :
|
56
|
+
:replace => {:target => "/root/a1/node()", :returns_self => false, :children_tags => %w[b1 b2]},
|
57
|
+
:swap => {:target => "/root/a1/node()", :returns_self => true, :children_tags => %w[b1 b2]},
|
58
58
|
|
59
|
-
:
|
59
|
+
:children= => {:target => "/root/a1", :returns_self => false, :children_tags => %w[b1 b2]},
|
60
|
+
:inner_html= => {:target => "/root/a1", :returns_self => true, :children_tags => %w[b1 b2]},
|
60
61
|
|
61
|
-
:add_previous_sibling => {:target => "/root/a1/text()", :
|
62
|
-
:previous= => {:target => "/root/a1/text()", :
|
63
|
-
:before => {:target => "/root/a1/text()", :
|
62
|
+
:add_previous_sibling => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[b1 b2 text]},
|
63
|
+
:previous= => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[b1 b2 text]},
|
64
|
+
:before => {:target => "/root/a1/text()", :returns_self => true, :children_tags => %w[b1 b2 text]},
|
64
65
|
|
65
|
-
:add_next_sibling => {:target => "/root/a1/text()", :
|
66
|
-
:next= => {:target => "/root/a1/text()", :
|
67
|
-
:after => {:target => "/root/a1/text()", :
|
66
|
+
:add_next_sibling => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[text b1 b2]},
|
67
|
+
:next= => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[text b1 b2]},
|
68
|
+
:after => {:target => "/root/a1/text()", :returns_self => true, :children_tags => %w[text b1 b2]}
|
68
69
|
}.each do |method, params|
|
69
70
|
|
70
71
|
before do
|
@@ -95,11 +96,12 @@ module Nokogiri
|
|
95
96
|
end
|
96
97
|
|
97
98
|
it "returns the expected value" do
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
sendee = @doc.at_xpath(params[:target])
|
100
|
+
result = sendee.send(method, @other_node)
|
101
|
+
if params[:returns_self]
|
102
|
+
result.must_equal sendee
|
101
103
|
else
|
102
|
-
|
104
|
+
result.must_equal @other_node
|
103
105
|
end
|
104
106
|
end
|
105
107
|
end
|
@@ -110,6 +112,17 @@ module Nokogiri
|
|
110
112
|
@doc.at_xpath(params[:target]).send(method, @fragment_string)
|
111
113
|
@doc.xpath("/root/a1/node()").collect {|n| n.name}.must_equal params[:children_tags]
|
112
114
|
end
|
115
|
+
|
116
|
+
it "returns the expected value" do
|
117
|
+
sendee = @doc.at_xpath(params[:target])
|
118
|
+
result = sendee.send(method, @fragment_string)
|
119
|
+
if params[:returns_self]
|
120
|
+
result.must_equal sendee
|
121
|
+
else
|
122
|
+
result.must_be_kind_of Nokogiri::XML::NodeSet
|
123
|
+
result.to_html.must_equal @fragment_string
|
124
|
+
end
|
125
|
+
end
|
113
126
|
end
|
114
127
|
describe "passed a fragment" do
|
115
128
|
it "inserts the fragment roots in the proper position" do
|
@@ -153,18 +166,6 @@ module Nokogiri
|
|
153
166
|
end
|
154
167
|
|
155
168
|
describe "ad hoc node reparenting behavior" do
|
156
|
-
before do
|
157
|
-
@xml = Nokogiri::XML "<root><a1>First node</a1><a2>Second node</a2><a3>Third node</a3></root>"
|
158
|
-
@html = Nokogiri::HTML(<<-eohtml)
|
159
|
-
<html>
|
160
|
-
<head></head>
|
161
|
-
<body>
|
162
|
-
<div class='baz'><a href="foo" class="bar">first</a></div>
|
163
|
-
</body>
|
164
|
-
</html>
|
165
|
-
eohtml
|
166
|
-
end
|
167
|
-
|
168
169
|
describe "#add_child" do
|
169
170
|
describe "given a new node with a namespace" do
|
170
171
|
it "keeps the namespace" do
|
@@ -223,7 +224,34 @@ module Nokogiri
|
|
223
224
|
end
|
224
225
|
end
|
225
226
|
|
227
|
+
describe "#add_previous_sibling" do
|
228
|
+
it "should not merge text nodes during the operation" do
|
229
|
+
xml = Nokogiri::XML %Q(<root>text node</root>)
|
230
|
+
replacee = xml.root.children.first
|
231
|
+
replacee.add_previous_sibling "foo <p></p> bar"
|
232
|
+
assert_equal "foo <p></p> bartext node", xml.root.children.to_html
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "#add_next_sibling" do
|
237
|
+
it "should not merge text nodes during the operation" do
|
238
|
+
xml = Nokogiri::XML %Q(<root>text node</root>)
|
239
|
+
replacee = xml.root.children.first
|
240
|
+
replacee.add_next_sibling "foo <p></p> bar"
|
241
|
+
assert_equal "text nodefoo <p></p> bar", xml.root.children.to_html
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
226
245
|
describe "#replace" do
|
246
|
+
describe "a text node with a text node" do
|
247
|
+
it "should not merge text nodes during the operation" do
|
248
|
+
xml = Nokogiri::XML %Q(<root>text node</root>)
|
249
|
+
replacee = xml.root.children.first
|
250
|
+
replacee.replace "new text node"
|
251
|
+
assert_equal "new text node", xml.root.children.first.content
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
227
255
|
describe "when a document has a default namespace" do
|
228
256
|
before do
|
229
257
|
@fruits = Nokogiri::XML(<<-eoxml)
|
@@ -260,10 +288,10 @@ module Nokogiri
|
|
260
288
|
</root>
|
261
289
|
EOHTML
|
262
290
|
|
263
|
-
root = doc.at("root")
|
264
|
-
a = root.at("a")
|
265
|
-
b = a.at("b")
|
266
|
-
c = a.at("c")
|
291
|
+
assert root = doc.at("root")
|
292
|
+
assert a = root.at("a")
|
293
|
+
assert b = a.at("b")
|
294
|
+
assert c = a.at("c")
|
267
295
|
a.add_next_sibling(b.unlink)
|
268
296
|
c.unlink
|
269
297
|
end
|
data/test/xml/test_node_set.rb
CHANGED
@@ -431,6 +431,19 @@ module Nokogiri
|
|
431
431
|
assert_equal 'employee', @xml.search("//wrapper").first.children[0].name
|
432
432
|
end
|
433
433
|
|
434
|
+
def test_wrap_a_fragment
|
435
|
+
frag = Nokogiri::XML::DocumentFragment.parse <<-EOXML
|
436
|
+
<employees>
|
437
|
+
<employee>hello</employee>
|
438
|
+
<employee>goodbye</employee>
|
439
|
+
</employees>
|
440
|
+
EOXML
|
441
|
+
employees = frag.xpath ".//employee"
|
442
|
+
employees.wrap("<wrapper/>")
|
443
|
+
assert_equal 'wrapper', employees[0].parent.name
|
444
|
+
assert_equal 'employee', frag.at(".//wrapper").children.first.name
|
445
|
+
end
|
446
|
+
|
434
447
|
def test_wrap_preserves_document_structure
|
435
448
|
assert_equal "employeeId",
|
436
449
|
@xml.at_xpath("//employee").children.detect{|j| ! j.text? }.name
|
data/test/xml/test_xpath.rb
CHANGED
@@ -61,6 +61,10 @@ module Nokogiri
|
|
61
61
|
}.new
|
62
62
|
end
|
63
63
|
|
64
|
+
def test_variable_binding
|
65
|
+
assert_equal 4, @xml.xpath('//address[@domestic=$value]', nil, :value => 'Yes').length
|
66
|
+
end
|
67
|
+
|
64
68
|
def test_unknown_attribute
|
65
69
|
assert_equal 0, @xml.xpath('//employee[@id="asdfasdf"]/@fooo').length
|
66
70
|
assert_nil @xml.xpath('//employee[@id="asdfasdf"]/@fooo')[0]
|
@@ -200,6 +204,34 @@ module Nokogiri
|
|
200
204
|
nokogiri = Nokogiri::HTML.parse(doc)
|
201
205
|
assert nokogiri.xpath(xpath)
|
202
206
|
end
|
207
|
+
|
208
|
+
def test_custom_xpath_handler_with_args_under_gc_pressure
|
209
|
+
# see http://github.com/tenderlove/nokogiri/issues/#issue/345
|
210
|
+
tool_inspector = Class.new do
|
211
|
+
def name_equals(nodeset, name, *args)
|
212
|
+
nodeset.all? do |node|
|
213
|
+
args.each { |thing| thing.inspect }
|
214
|
+
node["name"] == name
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end.new
|
218
|
+
|
219
|
+
xml = <<-EOXML
|
220
|
+
<toolbox>
|
221
|
+
#{"<tool name='hammer'/><tool name='wrench'/>" * 10}
|
222
|
+
</toolbox>
|
223
|
+
EOXML
|
224
|
+
doc = Nokogiri::XML xml
|
225
|
+
|
226
|
+
# long list of long arguments, to apply GC pressure during
|
227
|
+
# ruby_funcall argument marshalling
|
228
|
+
xpath = ["//tool[name_equals(.,'hammer'"]
|
229
|
+
1000.times { xpath << "'unused argument #{'x' * 1000}'" }
|
230
|
+
xpath << "'unused argument')]"
|
231
|
+
xpath = xpath.join(',')
|
232
|
+
|
233
|
+
assert_equal doc.xpath("//tool[@name='hammer']"), doc.xpath(xpath, tool_inspector)
|
234
|
+
end
|
203
235
|
end
|
204
236
|
end
|
205
237
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require "helper"
|
4
|
+
|
5
|
+
module Nokogiri
|
6
|
+
module XSLT
|
7
|
+
class TestCustomFunctions < Nokogiri::TestCase
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
@xml = Nokogiri.XML(<<-EOXML)
|
11
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
12
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
|
13
|
+
"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd">
|
14
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
15
|
+
<head>
|
16
|
+
<meta http-equiv="Content-type" content="application/xhtml+xml"/>
|
17
|
+
<title>Foo</title>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<h1>Foo</h1>
|
21
|
+
<p>Lorem ipsum.</p>
|
22
|
+
</body>
|
23
|
+
</html>
|
24
|
+
EOXML
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_function
|
28
|
+
skip("Pure Java version doesn't support this feature.") if !Nokogiri.uses_libxml?
|
29
|
+
foo = Class.new do
|
30
|
+
def capitalize nodes
|
31
|
+
nodes.first.content.upcase
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
XSLT.register "http://e.org/functions", foo
|
36
|
+
|
37
|
+
xsl = Nokogiri.XSLT(<<-EOXSL)
|
38
|
+
<?xml version="1.0"?>
|
39
|
+
<xsl:stylesheet version="1.0"
|
40
|
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
41
|
+
xmlns:f="http://e.org/functions"
|
42
|
+
extension-element-prefixes="f">
|
43
|
+
|
44
|
+
<xsl:template match="text()">
|
45
|
+
<xsl:copy-of select="f:capitalize(.)"/>
|
46
|
+
</xsl:template>
|
47
|
+
|
48
|
+
<xsl:template match="@*|node()">
|
49
|
+
<xsl:copy>
|
50
|
+
<xsl:apply-templates select="@*|node()"/>
|
51
|
+
<xsl:apply-imports/>
|
52
|
+
</xsl:copy>
|
53
|
+
</xsl:template>
|
54
|
+
|
55
|
+
</xsl:stylesheet>
|
56
|
+
EOXSL
|
57
|
+
result = xsl.transform @xml
|
58
|
+
assert_equal 'FOO', result.css('title').first.text
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_function_XSLT
|
62
|
+
skip("Pure Java version doesn't support this feature.") if !Nokogiri.uses_libxml?
|
63
|
+
foo = Class.new do
|
64
|
+
def america nodes
|
65
|
+
nodes.first.content.upcase
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
xsl = Nokogiri.XSLT(<<-EOXSL, "http://e.org/functions" => foo)
|
70
|
+
<?xml version="1.0"?>
|
71
|
+
<xsl:stylesheet version="1.0"
|
72
|
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
73
|
+
xmlns:f="http://e.org/functions"
|
74
|
+
extension-element-prefixes="f">
|
75
|
+
|
76
|
+
<xsl:template match="text()">
|
77
|
+
<xsl:copy-of select="f:america(.)"/>
|
78
|
+
</xsl:template>
|
79
|
+
|
80
|
+
<xsl:template match="@*|node()">
|
81
|
+
<xsl:copy>
|
82
|
+
<xsl:apply-templates select="@*|node()"/>
|
83
|
+
<xsl:apply-imports/>
|
84
|
+
</xsl:copy>
|
85
|
+
</xsl:template>
|
86
|
+
|
87
|
+
</xsl:stylesheet>
|
88
|
+
EOXSL
|
89
|
+
result = xsl.transform @xml
|
90
|
+
assert_equal 'FOO', result.css('title').first.text
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|