nokogiri 1.0.0-x86-mswin32-60

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.

Files changed (127) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +120 -0
  3. data/README.ja.txt +86 -0
  4. data/README.txt +87 -0
  5. data/Rakefile +264 -0
  6. data/ext/nokogiri/extconf.rb +59 -0
  7. data/ext/nokogiri/html_document.c +83 -0
  8. data/ext/nokogiri/html_document.h +10 -0
  9. data/ext/nokogiri/html_sax_parser.c +32 -0
  10. data/ext/nokogiri/html_sax_parser.h +11 -0
  11. data/ext/nokogiri/iconv.dll +0 -0
  12. data/ext/nokogiri/libexslt.dll +0 -0
  13. data/ext/nokogiri/libxml2.dll +0 -0
  14. data/ext/nokogiri/libxslt.dll +0 -0
  15. data/ext/nokogiri/native.c +40 -0
  16. data/ext/nokogiri/native.h +51 -0
  17. data/ext/nokogiri/native.so +0 -0
  18. data/ext/nokogiri/xml_cdata.c +52 -0
  19. data/ext/nokogiri/xml_cdata.h +9 -0
  20. data/ext/nokogiri/xml_document.c +159 -0
  21. data/ext/nokogiri/xml_document.h +10 -0
  22. data/ext/nokogiri/xml_dtd.c +117 -0
  23. data/ext/nokogiri/xml_dtd.h +8 -0
  24. data/ext/nokogiri/xml_node.c +709 -0
  25. data/ext/nokogiri/xml_node.h +15 -0
  26. data/ext/nokogiri/xml_node_set.c +124 -0
  27. data/ext/nokogiri/xml_node_set.h +9 -0
  28. data/ext/nokogiri/xml_reader.c +429 -0
  29. data/ext/nokogiri/xml_reader.h +10 -0
  30. data/ext/nokogiri/xml_sax_parser.c +174 -0
  31. data/ext/nokogiri/xml_sax_parser.h +10 -0
  32. data/ext/nokogiri/xml_syntax_error.c +194 -0
  33. data/ext/nokogiri/xml_syntax_error.h +11 -0
  34. data/ext/nokogiri/xml_text.c +29 -0
  35. data/ext/nokogiri/xml_text.h +9 -0
  36. data/ext/nokogiri/xml_xpath.c +46 -0
  37. data/ext/nokogiri/xml_xpath.h +11 -0
  38. data/ext/nokogiri/xml_xpath_context.c +81 -0
  39. data/ext/nokogiri/xml_xpath_context.h +9 -0
  40. data/ext/nokogiri/xslt_stylesheet.c +108 -0
  41. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  42. data/ext/nokogiri/zlib1.dll +0 -0
  43. data/lib/nokogiri.rb +51 -0
  44. data/lib/nokogiri/css.rb +6 -0
  45. data/lib/nokogiri/css/generated_parser.rb +653 -0
  46. data/lib/nokogiri/css/generated_tokenizer.rb +159 -0
  47. data/lib/nokogiri/css/node.rb +95 -0
  48. data/lib/nokogiri/css/parser.rb +24 -0
  49. data/lib/nokogiri/css/parser.y +198 -0
  50. data/lib/nokogiri/css/tokenizer.rb +9 -0
  51. data/lib/nokogiri/css/tokenizer.rex +63 -0
  52. data/lib/nokogiri/css/xpath_visitor.rb +165 -0
  53. data/lib/nokogiri/decorators.rb +1 -0
  54. data/lib/nokogiri/decorators/hpricot.rb +3 -0
  55. data/lib/nokogiri/decorators/hpricot/node.rb +58 -0
  56. data/lib/nokogiri/decorators/hpricot/node_set.rb +14 -0
  57. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +17 -0
  58. data/lib/nokogiri/hpricot.rb +47 -0
  59. data/lib/nokogiri/html.rb +95 -0
  60. data/lib/nokogiri/html/builder.rb +9 -0
  61. data/lib/nokogiri/html/document.rb +9 -0
  62. data/lib/nokogiri/html/sax/parser.rb +21 -0
  63. data/lib/nokogiri/version.rb +3 -0
  64. data/lib/nokogiri/xml.rb +67 -0
  65. data/lib/nokogiri/xml/after_handler.rb +18 -0
  66. data/lib/nokogiri/xml/before_handler.rb +32 -0
  67. data/lib/nokogiri/xml/builder.rb +79 -0
  68. data/lib/nokogiri/xml/cdata.rb +9 -0
  69. data/lib/nokogiri/xml/document.rb +30 -0
  70. data/lib/nokogiri/xml/dtd.rb +6 -0
  71. data/lib/nokogiri/xml/element.rb +6 -0
  72. data/lib/nokogiri/xml/entity_declaration.rb +9 -0
  73. data/lib/nokogiri/xml/node.rb +195 -0
  74. data/lib/nokogiri/xml/node_set.rb +183 -0
  75. data/lib/nokogiri/xml/notation.rb +6 -0
  76. data/lib/nokogiri/xml/reader.rb +14 -0
  77. data/lib/nokogiri/xml/sax.rb +9 -0
  78. data/lib/nokogiri/xml/sax/document.rb +59 -0
  79. data/lib/nokogiri/xml/sax/parser.rb +33 -0
  80. data/lib/nokogiri/xml/syntax_error.rb +21 -0
  81. data/lib/nokogiri/xml/text.rb +6 -0
  82. data/lib/nokogiri/xml/xpath.rb +6 -0
  83. data/lib/nokogiri/xml/xpath_context.rb +14 -0
  84. data/lib/nokogiri/xslt.rb +11 -0
  85. data/lib/nokogiri/xslt/stylesheet.rb +6 -0
  86. data/nokogiri.gemspec +34 -0
  87. data/test/css/test_nthiness.rb +159 -0
  88. data/test/css/test_parser.rb +224 -0
  89. data/test/css/test_tokenizer.rb +162 -0
  90. data/test/css/test_xpath_visitor.rb +54 -0
  91. data/test/files/staff.xml +59 -0
  92. data/test/files/staff.xslt +32 -0
  93. data/test/files/tlm.html +850 -0
  94. data/test/helper.rb +70 -0
  95. data/test/hpricot/files/basic.xhtml +17 -0
  96. data/test/hpricot/files/boingboing.html +2266 -0
  97. data/test/hpricot/files/cy0.html +3653 -0
  98. data/test/hpricot/files/immob.html +400 -0
  99. data/test/hpricot/files/pace_application.html +1320 -0
  100. data/test/hpricot/files/tenderlove.html +16 -0
  101. data/test/hpricot/files/uswebgen.html +220 -0
  102. data/test/hpricot/files/utf8.html +1054 -0
  103. data/test/hpricot/files/week9.html +1723 -0
  104. data/test/hpricot/files/why.xml +19 -0
  105. data/test/hpricot/load_files.rb +7 -0
  106. data/test/hpricot/test_alter.rb +67 -0
  107. data/test/hpricot/test_builder.rb +27 -0
  108. data/test/hpricot/test_parser.rb +423 -0
  109. data/test/hpricot/test_paths.rb +15 -0
  110. data/test/hpricot/test_preserved.rb +78 -0
  111. data/test/hpricot/test_xml.rb +30 -0
  112. data/test/html/sax/test_parser.rb +27 -0
  113. data/test/html/test_builder.rb +78 -0
  114. data/test/html/test_document.rb +86 -0
  115. data/test/test_convert_xpath.rb +180 -0
  116. data/test/test_nokogiri.rb +36 -0
  117. data/test/test_reader.rb +222 -0
  118. data/test/test_xslt_transforms.rb +29 -0
  119. data/test/xml/sax/test_parser.rb +93 -0
  120. data/test/xml/test_builder.rb +16 -0
  121. data/test/xml/test_cdata.rb +18 -0
  122. data/test/xml/test_document.rb +171 -0
  123. data/test/xml/test_dtd.rb +43 -0
  124. data/test/xml/test_node.rb +223 -0
  125. data/test/xml/test_node_set.rb +116 -0
  126. data/test/xml/test_text.rb +13 -0
  127. metadata +217 -0
@@ -0,0 +1,224 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
2
+
3
+ module Nokogiri
4
+ module CSS
5
+ class TestParser < Nokogiri::TestCase
6
+ def setup
7
+ @parser = Nokogiri::CSS::Parser.new
8
+ end
9
+
10
+ def test_find_by_type
11
+ ast = @parser.parse("a:nth-child(2)").first
12
+ matches = ast.find_by_type(
13
+ [:CONDITIONAL_SELECTOR,
14
+ [:ELEMENT_NAME],
15
+ [:PSEUDO_CLASS,
16
+ [:FUNCTION]
17
+ ]
18
+ ]
19
+ )
20
+ assert_equal(1, matches.length)
21
+ assert_equal(ast, matches.first)
22
+ end
23
+
24
+ def test_to_type
25
+ ast = @parser.parse("a:nth-child(2)").first
26
+ assert_equal(
27
+ [:CONDITIONAL_SELECTOR,
28
+ [:ELEMENT_NAME],
29
+ [:PSEUDO_CLASS,
30
+ [:FUNCTION]
31
+ ]
32
+ ], ast.to_type
33
+ )
34
+ end
35
+
36
+ def test_to_a
37
+ asts = @parser.parse("a:nth-child(2)")
38
+ assert_equal(
39
+ [:CONDITIONAL_SELECTOR,
40
+ [:ELEMENT_NAME, ["a"]],
41
+ [:PSEUDO_CLASS,
42
+ [:FUNCTION, ["nth-child("], ["2"]]
43
+ ]
44
+ ], asts.first.to_a
45
+ )
46
+ end
47
+
48
+ def test_function_with_arguments
49
+ assert_xpath "//*[position() = 2 and self::a]",
50
+ @parser.parse("a[2]")
51
+ assert_xpath "//*[position() = 2 and self::a]",
52
+ @parser.parse("a:nth-child(2)")
53
+ end
54
+
55
+ def test_carrot
56
+ assert_xpath "//a[starts-with(@id, 'Boing')]",
57
+ @parser.parse("a[id^='Boing']")
58
+ end
59
+
60
+ def test_attributes_with_at
61
+ ## This is non standard CSS
62
+ assert_xpath "//a[@id = 'Boing']",
63
+ @parser.parse("a[@id='Boing']")
64
+ end
65
+
66
+ def test_not_equal
67
+ ## This is non standard CSS
68
+ assert_xpath "//a[child::text() != 'Boing']",
69
+ @parser.parse("a[text()!='Boing']")
70
+ end
71
+
72
+ def test_function
73
+ ## This is non standard CSS
74
+ assert_xpath "//a[child::text()]",
75
+ @parser.parse("a[text()]")
76
+
77
+ ## This is non standard CSS
78
+ assert_xpath "//child::text()",
79
+ @parser.parse("text()")
80
+
81
+ ## This is non standard CSS
82
+ assert_xpath "//a[contains(child::text(), 'Boing')]",
83
+ @parser.parse("a[text()*='Boing']")
84
+
85
+ ## This is non standard CSS
86
+ assert_xpath "//script//comment()",
87
+ @parser.parse("script comment()")
88
+ end
89
+
90
+ def test_nonstandard_nth_selectors
91
+ ## These are non standard CSS
92
+ assert_xpath '//a[position() = 99]', @parser.parse('a:eq(99)')
93
+ assert_xpath '//a[position() = 1]', @parser.parse('a:first') # no parens
94
+ assert_xpath '//a[position() = last()]', @parser.parse('a:last') # no parens
95
+ assert_xpath '//a[position() = 99]', @parser.parse('a:nth(99)')
96
+ assert_xpath '//a[position() = 1]', @parser.parse('a:first()')
97
+ assert_xpath '//a[position() = last()]', @parser.parse('a:last()')
98
+ assert_xpath '//a[node()]', @parser.parse('a:parent')
99
+ end
100
+
101
+ def test_standard_nth_selectors
102
+ assert_xpath '//a[position() = 99]', @parser.parse('a:nth-of-type(99)')
103
+ assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type()')
104
+ assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type()')
105
+ assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type') # no parens
106
+ assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type') # no parens
107
+ assert_xpath '//a[position() = last() - 99]', @parser.parse('a:nth-last-of-type(99)')
108
+ assert_xpath '//a[position() = last() - 99]', @parser.parse('a:nth-last-of-type(99)')
109
+ end
110
+
111
+ def test_nth_child_selectors
112
+ assert_xpath '//*[position() = 1 and self::a]', @parser.parse('a:first-child')
113
+ assert_xpath '//*[position() = last() and self::a]', @parser.parse('a:last-child')
114
+ assert_xpath '//*[position() = 99 and self::a]', @parser.parse('a:nth-child(99)')
115
+ assert_xpath '//*[position() = last() - 99 and self::a]', @parser.parse('a:nth-last-child(99)')
116
+ end
117
+
118
+ def test_miscellaneous_selectors
119
+ assert_xpath '//*[last() = 1 and self::a]',
120
+ @parser.parse('a:only-child')
121
+ assert_xpath '//a[last() = 1]', @parser.parse('a:only-of-type')
122
+ assert_xpath '//a[not(node())]', @parser.parse('a:empty')
123
+ end
124
+
125
+ def test_nth_a_n_plus_b
126
+ assert_xpath '//a[(position() mod 2) = 0]', @parser.parse('a:nth-of-type(2n)')
127
+ assert_xpath '//a[(position() >= 1) and (((position()-1) mod 2) = 0)]', @parser.parse('a:nth-of-type(2n+1)')
128
+ assert_xpath '//a[(position() mod 2) = 0]', @parser.parse('a:nth-of-type(even)')
129
+ assert_xpath '//a[(position() >= 1) and (((position()-1) mod 2) = 0)]', @parser.parse('a:nth-of-type(odd)')
130
+ assert_xpath '//a[(position() >= 3) and (((position()-3) mod 4) = 0)]', @parser.parse('a:nth-of-type(4n+3)')
131
+ assert_xpath '//a[(position() <= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(-1n+3)')
132
+ assert_xpath '//a[(position() <= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(-n+3)')
133
+ assert_xpath '//a[(position() >= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(1n+3)')
134
+ assert_xpath '//a[(position() >= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(n+3)')
135
+ end
136
+
137
+ def test_preceding_selector
138
+ assert_xpath "//F[preceding-sibling::E]",
139
+ @parser.parse("E ~ F")
140
+ end
141
+
142
+ def test_direct_preceding_selector
143
+ assert_xpath "//E/following-sibling::*[1]/self::F",
144
+ @parser.parse("E + F")
145
+ end
146
+
147
+ def test_attribute
148
+ assert_xpath "//h1[@a = 'Tender Lovemaking']",
149
+ @parser.parse("h1[a='Tender Lovemaking']")
150
+ end
151
+
152
+ def test_id
153
+ assert_xpath "//*[@id = 'foo']", @parser.parse('#foo')
154
+ end
155
+
156
+ def test_pseudo_class_no_ident
157
+ assert_xpath "//*[1 = 1]", @parser.parse(':link')
158
+ end
159
+
160
+ def test_pseudo_class
161
+ assert_xpath "//a[1 = 1]", @parser.parse('a:link')
162
+ assert_xpath "//a[1 = 1]", @parser.parse('a:visited')
163
+ assert_xpath "//a[1 = 1]", @parser.parse('a:hover')
164
+ assert_xpath "//a[1 = 1]", @parser.parse('a:active')
165
+ assert_xpath "//a[1 = 1 and contains(concat(' ', @class, ' '), ' foo ')]",
166
+ @parser.parse('a:active.foo')
167
+ end
168
+
169
+ def test_star
170
+ assert_xpath "//*", @parser.parse('*')
171
+ assert_xpath "//*[contains(concat(' ', @class, ' '), ' pastoral ')]",
172
+ @parser.parse('*.pastoral')
173
+ end
174
+
175
+ def test_class
176
+ assert_xpath "//*[contains(concat(' ', @class, ' '), ' a ') and contains(concat(' ', @class, ' '), ' b ')]",
177
+ @parser.parse('.a.b')
178
+ assert_xpath "//*[contains(concat(' ', @class, ' '), ' awesome ')]",
179
+ @parser.parse('.awesome')
180
+ assert_xpath "//foo[contains(concat(' ', @class, ' '), ' awesome ')]",
181
+ @parser.parse('foo.awesome')
182
+ assert_xpath "//foo//*[contains(concat(' ', @class, ' '), ' awesome ')]",
183
+ @parser.parse('foo .awesome')
184
+ end
185
+
186
+ def test_ident
187
+ assert_xpath '//x', @parser.parse('x')
188
+ end
189
+
190
+ def test_parse_space
191
+ assert_xpath '//x//y', @parser.parse('x y')
192
+ end
193
+
194
+ def test_parse_descendant
195
+ assert_xpath '//x/y', @parser.parse('x > y')
196
+ end
197
+
198
+ def test_parse_slash
199
+ ## This is non standard CSS
200
+ assert_xpath '//x/y', @parser.parse('x/y')
201
+ end
202
+
203
+ def test_parse_doubleslash
204
+ ## This is non standard CSS
205
+ assert_xpath '//x//y', @parser.parse('x//y')
206
+ end
207
+
208
+ def test_multi_path
209
+ assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y, y > z')
210
+ assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y,y > z')
211
+ ###
212
+ # TODO: should we make this work?
213
+ # assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y | y > z')
214
+ end
215
+
216
+ def assert_xpath expecteds, asts
217
+ expecteds = [expecteds].flatten
218
+ expecteds.zip(asts).each do |expected, actual|
219
+ assert_equal expected, actual.to_xpath
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,162 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
2
+
3
+ module Nokogiri
4
+ module CSS
5
+ class TestTokenizer < Nokogiri::TestCase
6
+ def setup
7
+ @scanner = Nokogiri::CSS::Tokenizer.new
8
+ end
9
+
10
+ def test_not_equal
11
+ @scanner.scan("h1[a!='Tender Lovemaking']")
12
+ assert_tokens([ [:IDENT, 'h1'],
13
+ ['[', '['],
14
+ [:IDENT, 'a'],
15
+ [:NOT_EQUAL, '!='],
16
+ [:STRING, "'Tender Lovemaking'"],
17
+ [']', ']'],
18
+ ], @scanner)
19
+ end
20
+
21
+ def test_function
22
+ @scanner.scan("script comment()")
23
+ assert_tokens([ [:IDENT, 'script'],
24
+ [:S, ' '],
25
+ [:FUNCTION, 'comment('],
26
+ [')', ')'],
27
+ ], @scanner)
28
+ end
29
+
30
+ def test_preceding_selector
31
+ @scanner.scan("E ~ F")
32
+ assert_tokens([ [:IDENT, 'E'],
33
+ [:TILDE, ' ~'],
34
+ [:S, ' '],
35
+ [:IDENT, 'F'],
36
+ ], @scanner)
37
+ end
38
+
39
+ def test_scan_attribute_string
40
+ @scanner.scan("h1[a='Tender Lovemaking']")
41
+ assert_tokens([ [:IDENT, 'h1'],
42
+ ['[', '['],
43
+ [:IDENT, 'a'],
44
+ ['=', '='],
45
+ [:STRING, "'Tender Lovemaking'"],
46
+ [']', ']'],
47
+ ], @scanner)
48
+ @scanner.scan('h1[a="Tender Lovemaking"]')
49
+ assert_tokens([ [:IDENT, 'h1'],
50
+ ['[', '['],
51
+ [:IDENT, 'a'],
52
+ ['=', '='],
53
+ [:STRING, '"Tender Lovemaking"'],
54
+ [']', ']'],
55
+ ], @scanner)
56
+ end
57
+
58
+ def test_scan_id
59
+ @scanner.scan('#foo')
60
+ assert_tokens([ [:HASH, '#foo'] ], @scanner)
61
+ end
62
+
63
+ def test_scan_pseudo
64
+ @scanner.scan('a:visited')
65
+ assert_tokens([ [:IDENT, 'a'],
66
+ [':', ':'],
67
+ [:IDENT, 'visited']
68
+ ], @scanner)
69
+ end
70
+
71
+ def test_scan_star
72
+ @scanner.scan('*')
73
+ assert_tokens([ ['*', '*'], ], @scanner)
74
+ end
75
+
76
+ def test_scan_class
77
+ @scanner.scan('x.awesome')
78
+ assert_tokens([ [:IDENT, 'x'],
79
+ ['.', '.'],
80
+ [:IDENT, 'awesome'],
81
+ ], @scanner)
82
+ end
83
+
84
+ def test_scan_greater
85
+ @scanner.scan('x > y')
86
+ assert_tokens([ [:IDENT, 'x'],
87
+ [:GREATER, ' >'],
88
+ [:S, ' '],
89
+ [:IDENT, 'y']
90
+ ], @scanner)
91
+ end
92
+
93
+ def test_scan_slash
94
+ @scanner.scan('x/y')
95
+ assert_tokens([ [:IDENT, 'x'],
96
+ [:SLASH, '/'],
97
+ [:IDENT, 'y']
98
+ ], @scanner)
99
+ end
100
+
101
+ def test_scan_doubleslash
102
+ @scanner.scan('x//y')
103
+ assert_tokens([ [:IDENT, 'x'],
104
+ [:DOUBLESLASH, '//'],
105
+ [:IDENT, 'y']
106
+ ], @scanner)
107
+ end
108
+
109
+ def test_scan_function_selector
110
+ @scanner.scan('x:eq(0)')
111
+ assert_tokens([ [:IDENT, 'x'],
112
+ [':', ':'],
113
+ [:FUNCTION, 'eq('],
114
+ [:NUMBER, "0"],
115
+ [")", ")"]
116
+ ], @scanner)
117
+ end
118
+
119
+ def test_scan_an_plus_b
120
+ @scanner.scan('x:nth-child(5n+3)')
121
+ assert_tokens([ [:IDENT, 'x'],
122
+ [':', ':'],
123
+ [:FUNCTION, 'nth-child('],
124
+ [:NUMBER, '5'],
125
+ [:IDENT, 'n'],
126
+ [:PLUS, '+'],
127
+ [:NUMBER, '3'],
128
+ [")", ")"]
129
+ ], @scanner)
130
+
131
+ @scanner.scan('x:nth-child(-1n+3)')
132
+ assert_tokens([ [:IDENT, 'x'],
133
+ [':', ':'],
134
+ [:FUNCTION, 'nth-child('],
135
+ [:NUMBER, '-1'],
136
+ [:IDENT, 'n'],
137
+ [:PLUS, '+'],
138
+ [:NUMBER, '3'],
139
+ [")", ")"]
140
+ ], @scanner)
141
+
142
+ @scanner.scan('x:nth-child(-n+3)')
143
+ assert_tokens([ [:IDENT, 'x'],
144
+ [':', ':'],
145
+ [:FUNCTION, 'nth-child('],
146
+ [:IDENT, '-n'],
147
+ [:PLUS, '+'],
148
+ [:NUMBER, '3'],
149
+ [")", ")"]
150
+ ], @scanner)
151
+ end
152
+
153
+ def assert_tokens(tokens, scanner)
154
+ toks = []
155
+ while tok = @scanner.next_token
156
+ toks << tok
157
+ end
158
+ assert_equal(tokens, toks)
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,54 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
2
+
3
+ module Nokogiri
4
+ module CSS
5
+ class TestXPathVisitor < Nokogiri::TestCase
6
+ def setup
7
+ @parser = Nokogiri::CSS::Parser.new
8
+ end
9
+
10
+ def test_class_selectors
11
+ assert_xpath "//*[contains(concat(' ', @class, ' '), ' red ')]",
12
+ @parser.parse(".red")
13
+ end
14
+
15
+ def test_pipe
16
+ assert_xpath "//a[@id = 'Boing' or starts-with(@id, concat('Boing', '-'))]",
17
+ @parser.parse("a[id|='Boing']")
18
+ end
19
+
20
+ def test_custom_functions
21
+ visitor = Class.new(XPathVisitor) do
22
+ attr_accessor :awesome
23
+ def visit_function_aaron node
24
+ @awesome = true
25
+ 'aaron() = 1'
26
+ end
27
+ end.new
28
+ ast = @parser.parse('a:aaron()').first
29
+ assert_equal 'a[aaron() = 1]', visitor.accept(ast)
30
+ assert visitor.awesome
31
+ end
32
+
33
+ def test_custom_psuedo_classes
34
+ visitor = Class.new(XPathVisitor) do
35
+ attr_accessor :awesome
36
+ def visit_pseudo_class_aaron node
37
+ @awesome = true
38
+ 'aaron() = 1'
39
+ end
40
+ end.new
41
+ ast = @parser.parse('a:aaron').first
42
+ assert_equal 'a[aaron() = 1]', visitor.accept(ast)
43
+ assert visitor.awesome
44
+ end
45
+
46
+ def assert_xpath expecteds, asts
47
+ expecteds = [expecteds].flatten
48
+ expecteds.zip(asts).each do |expected, actual|
49
+ assert_equal expected, actual.to_xpath
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ <?xml version="1.0"?><?TEST-STYLE PIDATA?>
2
+ <!DOCTYPE staff SYSTEM "staff.dtd" [
3
+ <!ENTITY ent1 "es">
4
+ <!ENTITY ent2 "1900 Dallas Road">
5
+ <!ENTITY ent3 "Texas">
6
+ <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
7
+ <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
8
+ <!ENTITY ent1 "This entity should be discarded">
9
+ <!ELEMENT br EMPTY>
10
+ <!ATTLIST br width CDATA "0">
11
+ <!NOTATION notation1 PUBLIC "notation1File">
12
+ <!NOTATION notation2 SYSTEM "notation2File">
13
+ ]>
14
+ <!-- This is comment number 1.-->
15
+ <staff>
16
+ <employee>
17
+ <employeeId>EMP0001</employeeId>
18
+ <name>Margaret Martin</name>
19
+ <position>Accountant</position>
20
+ <salary>56,000</salary>
21
+ <gender>Female</gender>
22
+ <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
23
+ </employee>
24
+ <employee>
25
+ <employeeId>EMP0002</employeeId>
26
+ <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
27
+ <![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
28
+ <position>Secretary</position>
29
+ <salary>35,000</salary>
30
+ <gender>Female</gender>
31
+ <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
32
+ 98554</address>
33
+ </employee>
34
+ <employee>
35
+ <employeeId>EMP0003</employeeId>
36
+ <name>Roger
37
+ Jones</name>
38
+ <position>Department Manager</position>
39
+ <salary>100,000</salary>
40
+ <gender>&ent4;</gender>
41
+ <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
42
+ </employee>
43
+ <employee>
44
+ <employeeId>EMP0004</employeeId>
45
+ <name>Jeny Oconnor</name>
46
+ <position>Personnel Director</position>
47
+ <salary>95,000</salary>
48
+ <gender>Female</gender>
49
+ <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address>
50
+ </employee>
51
+ <employee>
52
+ <employeeId>EMP0005</employeeId>
53
+ <name>Robert Myers</name>
54
+ <position>Computer Specialist</position>
55
+ <salary>90,000</salary>
56
+ <gender>male</gender>
57
+ <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address>
58
+ </employee>
59
+ </staff>