oga 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,6 +27,30 @@ module Oga
27
27
 
28
28
  return result.is_a?(XML::NodeSet) ? result.first : result
29
29
  end
30
+
31
+ ##
32
+ # Evaluates the given CSS expression.
33
+ #
34
+ # @param [String] expression The CSS expression to run.
35
+ # @see [Oga::XPath::Evaluator#initialize]
36
+ #
37
+ def css(expression)
38
+ ast = CSS::Parser.new(expression).parse
39
+
40
+ return XPath::Evaluator.new(self).evaluate_ast(ast)
41
+ end
42
+
43
+ ##
44
+ # Evaluates the given CSS expression and returns the first node in the
45
+ # set.
46
+ #
47
+ # @see [#css]
48
+ #
49
+ def at_css(*args)
50
+ result = css(*args)
51
+
52
+ return result.is_a?(XML::NodeSet) ? result.first : result
53
+ end
30
54
  end # Querying
31
55
  end # XML
32
56
  end # Oga
@@ -37,6 +37,26 @@ module Oga
37
37
  # For information on the callback arguments see the documentation of the
38
38
  # corresponding methods in {Oga::XML::Parser}.
39
39
  #
40
+ # ## Element Callbacks
41
+ #
42
+ # The SAX parser changes the behaviour of both `on_element` and
43
+ # `after_element`. The latter in the regular parser only takes a
44
+ # {Oga::XML::Element} instance. In the SAX parser it will instead take a
45
+ # namespace name and the element name. This eases the process of figuring
46
+ # out what element a callback is associated with.
47
+ #
48
+ # An example:
49
+ #
50
+ # class SaxHandler
51
+ # def on_element(namespace, name, attrs = {})
52
+ # # ...
53
+ # end
54
+ #
55
+ # def after_element(namespace, name)
56
+ # puts name # => "foo", "bar", etc
57
+ # end
58
+ # end
59
+ #
40
60
  class SaxParser < Parser
41
61
  ##
42
62
  # @param [Object] handler The SAX handler to delegate callbacks to.
@@ -52,12 +72,46 @@ module Oga
52
72
  instance_methods.grep(/^(on_|after_)/).each do |method|
53
73
  eval <<-EOF, nil, __FILE__, __LINE__ + 1
54
74
  def #{method}(*args)
55
- @handler.#{method}(*args) if @handler.respond_to?(:#{method})
75
+ run_callback(:#{method}, *args)
56
76
 
57
77
  return
58
78
  end
59
79
  EOF
60
80
  end
81
+
82
+ ##
83
+ # Manually overwrite `on_element` so we can ensure that `after_element`
84
+ # always receives the namespace and name.
85
+ #
86
+ # @see [Oga::XML::Parser#on_element]
87
+ # @return [Array]
88
+ #
89
+ def on_element(namespace, name, attrs = {})
90
+ run_callback(:on_element, namespace, name, attrs)
91
+
92
+ return namespace, name
93
+ end
94
+
95
+ ##
96
+ # Manually overwrite `after_element` so it can take a namespace and name.
97
+ # This differs a bit from the regular `after_element` which only takes an
98
+ # {Oga::XML::Element} instance.
99
+ #
100
+ # @param [Array] namespace_with_name
101
+ #
102
+ def after_element(namespace_with_name)
103
+ run_callback(:after_element, *namespace_with_name)
104
+ end
105
+
106
+ private
107
+
108
+ ##
109
+ # @param [Symbol] method
110
+ # @param [Array] args
111
+ #
112
+ def run_callback(method, *args)
113
+ @handler.send(method, *args) if @handler.respond_to?(method)
114
+ end
61
115
  end # SaxParser
62
116
  end # XML
63
117
  end # Oga
@@ -5,7 +5,12 @@ module Oga
5
5
  # have any children, attributes and the likes; just text.
6
6
  #
7
7
  class Text < CharacterNode
8
-
8
+ ##
9
+ # @see [Oga::XML::CharacterNode#to_xml]
10
+ #
11
+ def to_xml
12
+ return Entities.encode(super)
13
+ end
9
14
  end # Text
10
15
  end # XML
11
16
  end # Oga
@@ -2,7 +2,7 @@ module Oga
2
2
  module XPath
3
3
  ##
4
4
  # The Evaluator class evaluates XPath expressions, either as a String or an
5
- # AST of {Oga::XPath::Node} instances.
5
+ # AST of `AST::Node` instances.
6
6
  #
7
7
  # ## Thread Safety
8
8
  #
@@ -90,7 +90,7 @@ module Oga
90
90
  ##
91
91
  # Evaluates a pre-parsed XPath expression.
92
92
  #
93
- # @param [Oga::XPath::Node] ast
93
+ # @param [AST::Node] ast
94
94
  # @return [Mixed]
95
95
  #
96
96
  def evaluate_ast(ast)
@@ -104,7 +104,7 @@ module Oga
104
104
  # dedicated handler method. Handler methods are called "on_X" where "X" is
105
105
  # the node type.
106
106
  #
107
- # @param [Oga::XPath::Node] ast_node The XPath AST node to process.
107
+ # @param [AST::Node] ast_node The XPath AST node to process.
108
108
  #
109
109
  # @param [Oga::XML::NodeSet] context The context (a set of nodes) to
110
110
  # evaluate an expression in.
@@ -120,7 +120,7 @@ module Oga
120
120
  ##
121
121
  # Processes an absolute XPath expression such as `/foo`.
122
122
  #
123
- # @param [Oga::XPath::Node] ast_node
123
+ # @param [AST::Node] ast_node
124
124
  # @param [Oga::XML::NodeSet] context
125
125
  # @return [Oga::XML::NodeSet]
126
126
  #
@@ -142,7 +142,7 @@ module Oga
142
142
  # `&&` / `and` operator. Whenever a path results in an empty node set the
143
143
  # evaluation is aborted immediately.
144
144
  #
145
- # @param [Oga::XPath::Node] ast_node
145
+ # @param [AST::Node] ast_node
146
146
  # @param [Oga::XML::NodeSet] context
147
147
  # @return [Oga::XML::NodeSet]
148
148
  #
@@ -163,28 +163,45 @@ module Oga
163
163
  end
164
164
 
165
165
  ##
166
- # Processes a node test and optionally a predicate.
166
+ # Processes a node test.
167
167
  #
168
- # @param [Oga::XPath::Node] ast_node
168
+ # @param [AST::Node] ast_node
169
169
  # @param [Oga::XML::NodeSet] context
170
170
  # @return [Oga::XML::NodeSet]
171
171
  #
172
172
  def on_test(ast_node, context)
173
- nodes = XML::NodeSet.new
174
- predicate = ast_node.children[2]
175
- xpath_index = 1
173
+ nodes = XML::NodeSet.new
176
174
 
177
175
  context.each do |xml_node|
178
- next unless node_matches?(xml_node, ast_node)
176
+ nodes << xml_node if node_matches?(xml_node, ast_node)
177
+ end
178
+
179
+ return nodes
180
+ end
181
+
182
+ ##
183
+ # Processes a predicate.
184
+ #
185
+ # @param [AST::Node] ast_node
186
+ # @param [Oga::XML::NodeSet] context
187
+ # @return [Oga::XML::NodeSet]
188
+ #
189
+ def on_predicate(ast_node, context)
190
+ test, predicate = *ast_node
191
+ final_nodes = XML::NodeSet.new
192
+
193
+ context.each do |context_node|
194
+ initial_nodes = process(test, XML::NodeSet.new([context_node]))
195
+ xpath_index = 1
179
196
 
180
- if predicate
181
- retval = with_node_set(context) do
197
+ initial_nodes.each do |xml_node|
198
+ retval = with_node_set(initial_nodes) do
182
199
  process(predicate, XML::NodeSet.new([xml_node]))
183
200
  end
184
201
 
185
202
  # Numeric values are used as node set indexes.
186
203
  if retval.is_a?(Numeric)
187
- nodes << xml_node if retval.to_i == xpath_index
204
+ final_nodes << xml_node if retval.to_i == xpath_index
188
205
 
189
206
  # Node sets, strings, booleans, etc
190
207
  elsif retval
@@ -192,16 +209,14 @@ module Oga
192
209
  next
193
210
  end
194
211
 
195
- nodes << xml_node
212
+ final_nodes << xml_node
196
213
  end
197
- else
198
- nodes << xml_node
199
- end
200
214
 
201
- xpath_index += 1
215
+ xpath_index += 1
216
+ end
202
217
  end
203
218
 
204
- return nodes
219
+ return final_nodes
205
220
  end
206
221
 
207
222
  ##
@@ -209,7 +224,7 @@ module Oga
209
224
  # similar to {#process} except the handler names are "on_axis_X" with "X"
210
225
  # being the axis name.
211
226
  #
212
- # @param [Oga::XPath::Node] ast_node
227
+ # @param [AST::Node] ast_node
213
228
  # @param [Oga::XML::NodeSet] context
214
229
  # @return [Oga::XML::NodeSet]
215
230
  #
@@ -228,7 +243,7 @@ module Oga
228
243
  # Evaluation happens using a "short-circuit" mechanism. The moment a
229
244
  # matching node is found it is returned immediately.
230
245
  #
231
- # @param [Oga::XPath::Node] ast_node
246
+ # @param [AST::Node] ast_node
232
247
  # @param [Oga::XML::NodeSet] context
233
248
  # @return [Oga::XML::NodeSet]
234
249
  #
@@ -279,7 +294,7 @@ module Oga
279
294
  # (unlike some other methods which return the moment they find a matching
280
295
  # node).
281
296
  #
282
- # @param [Oga::XPath::Node] ast_node
297
+ # @param [AST::Node] ast_node
283
298
  # @param [Oga::XML::NodeSet] context
284
299
  # @return [Oga::XML::NodeSet]
285
300
  #
@@ -299,7 +314,7 @@ module Oga
299
314
  # Evaluates the `child` axis. This axis simply takes all the child nodes
300
315
  # of the current context nodes.
301
316
  #
302
- # @param [Oga::XPath::Node] ast_node
317
+ # @param [AST::Node] ast_node
303
318
  # @param [Oga::XML::NodeSet] context
304
319
  # @return [Oga::XML::NodeSet]
305
320
  #
@@ -311,7 +326,7 @@ module Oga
311
326
  # Evaluates the `descendant` axis. This method processes child nodes until
312
327
  # the very end of the tree, no "short-circuiting" mechanism is used.
313
328
  #
314
- # @param [Oga::XPath::Node] ast_node
329
+ # @param [AST::Node] ast_node
315
330
  # @param [Oga::XML::NodeSet] context
316
331
  # @return [Oga::XML::NodeSet]
317
332
  #
@@ -319,12 +334,8 @@ module Oga
319
334
  nodes = XML::NodeSet.new
320
335
 
321
336
  context.each do |context_node|
322
- context_node.children.each do |node|
323
- nodes << node if node_matches?(node, ast_node)
324
- end
325
-
326
337
  context_node.each_node do |node|
327
- nodes << node if node_matches?(node, ast_node)
338
+ nodes.concat(process(ast_node, XML::NodeSet.new([node])))
328
339
  end
329
340
  end
330
341
 
@@ -334,7 +345,7 @@ module Oga
334
345
  ##
335
346
  # Evaluates the `descendant-or-self` axis.
336
347
  #
337
- # @param [Oga::XPath::Node] ast_node
348
+ # @param [AST::Node] ast_node
338
349
  # @param [Oga::XML::NodeSet] context
339
350
  # @return [Oga::XML::NodeSet]
340
351
  #
@@ -349,17 +360,18 @@ module Oga
349
360
  ##
350
361
  # Evaluates the `following` axis.
351
362
  #
352
- # @param [Oga::XPath::Node] ast_node
363
+ # @param [AST::Node] ast_node
353
364
  # @param [Oga::XML::NodeSet] context
354
365
  # @return [Oga::XML::NodeSet]
355
366
  #
356
367
  def on_axis_following(ast_node, context)
357
368
  nodes = XML::NodeSet.new
369
+ root = root_node(@document)
358
370
 
359
371
  context.each do |context_node|
360
372
  check = false
361
373
 
362
- @document.each_node do |doc_node|
374
+ root.each_node do |doc_node|
363
375
  # Skip child nodes of the current context node, compare all
364
376
  # following nodes.
365
377
  if doc_node == context_node
@@ -379,18 +391,19 @@ module Oga
379
391
  ##
380
392
  # Evaluates the `following-sibling` axis.
381
393
  #
382
- # @param [Oga::XPath::Node] ast_node
394
+ # @param [AST::Node] ast_node
383
395
  # @param [Oga::XML::NodeSet] context
384
396
  # @return [Oga::XML::NodeSet]
385
397
  #
386
398
  def on_axis_following_sibling(ast_node, context)
387
399
  nodes = XML::NodeSet.new
400
+ root = parent_node(@document)
388
401
 
389
402
  context.each do |context_node|
390
403
  check = false
391
404
  parent = has_parent?(context_node) ? context_node.parent : nil
392
405
 
393
- @document.each_node do |doc_node|
406
+ root.each_node do |doc_node|
394
407
  # Skip child nodes of the current context node, compare all
395
408
  # following nodes.
396
409
  if doc_node == context_node
@@ -416,7 +429,7 @@ module Oga
416
429
  ##
417
430
  # Evaluates the `parent` axis.
418
431
  #
419
- # @param [Oga::XPath::Node] ast_node
432
+ # @param [AST::Node] ast_node
420
433
  # @param [Oga::XML::NodeSet] context
421
434
  # @return [Oga::XML::NodeSet]
422
435
  #
@@ -437,17 +450,18 @@ module Oga
437
450
  ##
438
451
  # Evaluates the `preceding` axis.
439
452
  #
440
- # @param [Oga::XPath::Node] ast_node
453
+ # @param [AST::Node] ast_node
441
454
  # @param [Oga::XML::NodeSet] context
442
455
  # @return [Oga::XML::NodeSet]
443
456
  #
444
457
  def on_axis_preceding(ast_node, context)
445
458
  nodes = XML::NodeSet.new
459
+ root = root_node(@document)
446
460
 
447
461
  context.each do |context_node|
448
462
  check = true
449
463
 
450
- @document.each_node do |doc_node|
464
+ root.each_node do |doc_node|
451
465
  # Test everything *until* we hit the current context node.
452
466
  if doc_node == context_node
453
467
  break
@@ -463,18 +477,19 @@ module Oga
463
477
  ##
464
478
  # Evaluates the `preceding-sibling` axis.
465
479
  #
466
- # @param [Oga::XPath::Node] ast_node
480
+ # @param [AST::Node] ast_node
467
481
  # @param [Oga::XML::NodeSet] context
468
482
  # @return [Oga::XML::NodeSet]
469
483
  #
470
484
  def on_axis_preceding_sibling(ast_node, context)
471
485
  nodes = XML::NodeSet.new
486
+ root = parent_node(@document)
472
487
 
473
488
  context.each do |context_node|
474
489
  check = true
475
490
  parent = has_parent?(context_node) ? context_node.parent : nil
476
491
 
477
- @document.each_node do |doc_node|
492
+ root.each_node do |doc_node|
478
493
  # Test everything *until* we hit the current context node.
479
494
  if doc_node == context_node
480
495
  break
@@ -490,7 +505,7 @@ module Oga
490
505
  ##
491
506
  # Evaluates the `self` axis.
492
507
  #
493
- # @param [Oga::XPath::Node] ast_node
508
+ # @param [AST::Node] ast_node
494
509
  # @param [Oga::XML::NodeSet] context
495
510
  # @return [Oga::XML::NodeSet]
496
511
  #
@@ -507,7 +522,7 @@ module Oga
507
522
  ##
508
523
  # Evaluates the `namespace` axis.
509
524
  #
510
- # @param [Oga::XPath::Node] ast_node
525
+ # @param [AST::Node] ast_node
511
526
  # @param [Oga::XML::NodeSet] context
512
527
  # @return [Oga::XML::NodeSet]
513
528
  #
@@ -531,7 +546,7 @@ module Oga
531
546
  ##
532
547
  # Dispatches node type matching to dedicated handlers.
533
548
  #
534
- # @param [Oga::XPath::Node] ast_node
549
+ # @param [AST::Node] ast_node
535
550
  # @param [Oga::XML::NodeSet] context
536
551
  # @return [Oga::XML::NodeSet]
537
552
  #
@@ -546,7 +561,7 @@ module Oga
546
561
  ##
547
562
  # Processes the `node` type matcher. This matcher matches all node types.
548
563
  #
549
- # @param [Oga::XPath::Node] ast_node
564
+ # @param [AST::Node] ast_node
550
565
  # @param [Oga::XML::NodeSet] context
551
566
  # @return [Oga::XML::NodeSet]
552
567
  #
@@ -554,7 +569,9 @@ module Oga
554
569
  nodes = XML::NodeSet.new
555
570
 
556
571
  context.each do |node|
557
- nodes << node if node.is_a?(XML::Node)
572
+ if node.is_a?(XML::Node) or node.is_a?(XML::Document)
573
+ nodes << node
574
+ end
558
575
  end
559
576
 
560
577
  return nodes
@@ -563,7 +580,7 @@ module Oga
563
580
  ##
564
581
  # Processes the `text()` type test. This matches only text nodes.
565
582
  #
566
- # @param [Oga::XPath::Node] ast_node
583
+ # @param [AST::Node] ast_node
567
584
  # @param [Oga::XML::NodeSet] context
568
585
  # @return [Oga::XML::NodeSet]
569
586
  #
@@ -580,7 +597,7 @@ module Oga
580
597
  ##
581
598
  # Processes the `comment()` type test. This matches only comment nodes.
582
599
  #
583
- # @param [Oga::XPath::Node] ast_node
600
+ # @param [AST::Node] ast_node
584
601
  # @param [Oga::XML::NodeSet] context
585
602
  # @return [Oga::XML::NodeSet]
586
603
  #
@@ -598,7 +615,7 @@ module Oga
598
615
  # Processes the `processing-instruction()` type test. This matches only
599
616
  # processing-instruction nodes.
600
617
  #
601
- # @param [Oga::XPath::Node] ast_node
618
+ # @param [AST::Node] ast_node
602
619
  # @param [Oga::XML::NodeSet] context
603
620
  # @return [Oga::XML::NodeSet]
604
621
  #
@@ -616,7 +633,7 @@ module Oga
616
633
  # Processes the pipe (`|`) operator. This operator creates a union of two
617
634
  # sets.
618
635
  #
619
- # @param [Oga::XPath::Node] ast_node
636
+ # @param [AST::Node] ast_node
620
637
  # @param [Oga::XML::NodeSet] context
621
638
  # @return [Oga::XML::NodeSet]
622
639
  #
@@ -633,7 +650,7 @@ module Oga
633
650
  # evaluate to `true`. If the first expression evaluates to `false` the
634
651
  # right expression is ignored.
635
652
  #
636
- # @param [Oga::XPath::Node] ast_node
653
+ # @param [AST::Node] ast_node
637
654
  # @param [Oga::XML::NodeSet] context
638
655
  # @return [TrueClass|FalseClass]
639
656
  #
@@ -650,7 +667,7 @@ module Oga
650
667
  # true, otherwise false is returned. If the first expression evaluates to
651
668
  # `true` the second expression is ignored.
652
669
  #
653
- # @param [Oga::XPath::Node] ast_node
670
+ # @param [AST::Node] ast_node
654
671
  # @param [Oga::XML::NodeSet] context
655
672
  # @return [TrueClass|FalseClass]
656
673
  #
@@ -666,7 +683,7 @@ module Oga
666
683
  # This operator converts the left and right expressions to numbers and
667
684
  # adds them together.
668
685
  #
669
- # @param [Oga::XPath::Node] ast_node
686
+ # @param [AST::Node] ast_node
670
687
  # @param [Oga::XML::NodeSet] context
671
688
  # @return [Float]
672
689
  #
@@ -682,7 +699,7 @@ module Oga
682
699
  # This operator converts the left and right expressions to numbers and
683
700
  # divides the left number with the right number.
684
701
  #
685
- # @param [Oga::XPath::Node] ast_node
702
+ # @param [AST::Node] ast_node
686
703
  # @param [Oga::XML::NodeSet] context
687
704
  # @return [Float]
688
705
  #
@@ -698,7 +715,7 @@ module Oga
698
715
  # This operator converts the left and right expressions to numbers and
699
716
  # returns the modulo of the two numbers.
700
717
  #
701
- # @param [Oga::XPath::Node] ast_node
718
+ # @param [AST::Node] ast_node
702
719
  # @param [Oga::XML::NodeSet] context
703
720
  # @return [Float]
704
721
  #
@@ -714,7 +731,7 @@ module Oga
714
731
  # This operator converts the left and right expressions to numbers and
715
732
  # multiplies the left number with the right number.
716
733
  #
717
- # @param [Oga::XPath::Node] ast_node
734
+ # @param [AST::Node] ast_node
718
735
  # @param [Oga::XML::NodeSet] context
719
736
  # @return [Float]
720
737
  #
@@ -730,7 +747,7 @@ module Oga
730
747
  # This operator converts the left and right expressions to numbers and
731
748
  # subtracts the right number of the left number.
732
749
  #
733
- # @param [Oga::XPath::Node] ast_node
750
+ # @param [AST::Node] ast_node
734
751
  # @param [Oga::XML::NodeSet] context
735
752
  # @return [Float]
736
753
  #
@@ -749,7 +766,7 @@ module Oga
749
766
  # compared instead of the nodes themselves. That is, nodes with different
750
767
  # names but the same text are considered to be equal.
751
768
  #
752
- # @param [Oga::XPath::Node] ast_node
769
+ # @param [AST::Node] ast_node
753
770
  # @param [Oga::XML::NodeSet] context
754
771
  # @return [TrueClass|FalseClass]
755
772
  #
@@ -863,7 +880,7 @@ module Oga
863
880
  # 2. A variable list of XPath function arguments, passed as individual
864
881
  # Ruby method arguments.
865
882
  #
866
- # @param [Oga::XPath::Node] ast_node
883
+ # @param [AST::Node] ast_node
867
884
  # @param [Oga::XML::NodeSet] context
868
885
  # @return [Oga::XML::NodeSet]
869
886
  #
@@ -905,7 +922,7 @@ module Oga
905
922
  # of nodes in `expression` and returns the result as a float.
906
923
  #
907
924
  # @param [Oga::XML::NodeSet] context
908
- # @param [Oga::XPath::Node] expression
925
+ # @param [AST::Node] expression
909
926
  # @return [Float]
910
927
  #
911
928
  def on_call_count(context, expression)
@@ -933,7 +950,7 @@ module Oga
933
950
  # regardless of the current position.
934
951
  #
935
952
  # @param [Oga::XML::NodeSet] context
936
- # @param [Oga::XPath::Node] expression
953
+ # @param [AST::Node] expression
937
954
  # @return [Oga::XML::NodeSet]
938
955
  #
939
956
  def on_call_id(context, expression)
@@ -967,7 +984,7 @@ module Oga
967
984
  # * The first node in the supplied node set
968
985
  #
969
986
  # @param [Oga::XML::NodeSet] context
970
- # @param [Oga::XPath::Node] expression
987
+ # @param [AST::Node] expression
971
988
  # @return [Oga::XML::NodeSet]
972
989
  #
973
990
  def on_call_local_name(context, expression = nil)
@@ -984,7 +1001,7 @@ module Oga
984
1001
  # present.
985
1002
  #
986
1003
  # @param [Oga::XML::NodeSet] context
987
- # @param [Oga::XPath::Node] expression
1004
+ # @param [AST::Node] expression
988
1005
  # @return [Oga::XML::NodeSet]
989
1006
  #
990
1007
  def on_call_name(context, expression = nil)
@@ -1010,7 +1027,7 @@ module Oga
1010
1027
  # * The first node in the supplied node set
1011
1028
  #
1012
1029
  # @param [Oga::XML::NodeSet] context
1013
- # @param [Oga::XPath::Node] expression
1030
+ # @param [AST::Node] expression
1014
1031
  # @return [Oga::XML::NodeSet]
1015
1032
  #
1016
1033
  def on_call_namespace_uri(context, expression = nil)
@@ -1034,7 +1051,7 @@ module Oga
1034
1051
  # string(10) # => "10"
1035
1052
  #
1036
1053
  # @param [Oga::XML::NodeSet] context
1037
- # @param [Oga::XPath::Node] expression
1054
+ # @param [AST::Node] expression
1038
1055
  # @return [String]
1039
1056
  #
1040
1057
  def on_call_string(context, expression = nil)
@@ -1066,7 +1083,7 @@ module Oga
1066
1083
  #
1067
1084
  # @see [#on_call_string]
1068
1085
  # @param [Oga::XML::NodeSet] context
1069
- # @param [Oga::XPath::Node] expression
1086
+ # @param [AST::Node] expression
1070
1087
  # @return [Float]
1071
1088
  #
1072
1089
  def on_call_number(context, expression = nil)
@@ -1101,9 +1118,9 @@ module Oga
1101
1118
  # them. In case of node sets the text of the set is used.
1102
1119
  #
1103
1120
  # @param [Oga::XML::NodeSet] context
1104
- # @param [Oga::XPath::Node] first
1105
- # @param [Oga::XPath::Node] second
1106
- # @param [Array<Oga::XPath::Node>] rest
1121
+ # @param [AST::Node] first
1122
+ # @param [AST::Node] second
1123
+ # @param [Array<AST::Node>] rest
1107
1124
  #
1108
1125
  def on_call_concat(context, first, second, *rest)
1109
1126
  args = [first, second] + rest
@@ -1126,8 +1143,8 @@ module Oga
1126
1143
  # starts-with("hello world", "hello") # => true
1127
1144
  #
1128
1145
  # @param [Oga::XML::NodeSet] context
1129
- # @param [Oga::XPath::Node] haystack The string to search.
1130
- # @param [Oga::XPath::Node] needle The string to search for.
1146
+ # @param [AST::Node] haystack The string to search.
1147
+ # @param [AST::Node] needle The string to search for.
1131
1148
  # @return [TrueClass|FalseClass]
1132
1149
  #
1133
1150
  def on_call_starts_with(context, haystack, needle)
@@ -1148,8 +1165,8 @@ module Oga
1148
1165
  # contains("hello world", "o w") # => true
1149
1166
  #
1150
1167
  # @param [Oga::XML::NodeSet] context
1151
- # @param [Oga::XPath::Node] haystack The string to search.
1152
- # @param [Oga::XPath::Node] needle The string to search for.
1168
+ # @param [AST::Node] haystack The string to search.
1169
+ # @param [AST::Node] needle The string to search for.
1153
1170
  # @return [String]
1154
1171
  #
1155
1172
  def on_call_contains(context, haystack, needle)
@@ -1170,8 +1187,8 @@ module Oga
1170
1187
  # This would return "2014" as it occurs before the first "-".
1171
1188
  #
1172
1189
  # @param [Oga::XML::NodeSet] context
1173
- # @param [Oga::XPath::Node] haystack The string to search.
1174
- # @param [Oga::XPath::Node] needle The string to search for.
1190
+ # @param [AST::Node] haystack The string to search.
1191
+ # @param [AST::Node] needle The string to search for.
1175
1192
  # @return [String]
1176
1193
  #
1177
1194
  def on_call_substring_before(context, haystack, needle)
@@ -1194,8 +1211,8 @@ module Oga
1194
1211
  # This would return "08-25" as it occurs after the first "-".
1195
1212
  #
1196
1213
  # @param [Oga::XML::NodeSet] context
1197
- # @param [Oga::XPath::Node] haystack The string to search.
1198
- # @param [Oga::XPath::Node] needle The string to search for.
1214
+ # @param [AST::Node] haystack The string to search.
1215
+ # @param [AST::Node] needle The string to search for.
1199
1216
  # @return [String]
1200
1217
  #
1201
1218
  def on_call_substring_after(context, haystack, needle)
@@ -1227,9 +1244,9 @@ module Oga
1227
1244
  # substring(users/user/username, 5)
1228
1245
  #
1229
1246
  # @param [Oga::XML::NodeSet] context
1230
- # @param [Oga::XPath::Node] haystack
1231
- # @param [Oga::XPath::Node] start
1232
- # @param [Oga::XPath::Node] length
1247
+ # @param [AST::Node] haystack
1248
+ # @param [AST::Node] start
1249
+ # @param [AST::Node] length
1233
1250
  # @return [String]
1234
1251
  #
1235
1252
  def on_call_substring(context, haystack, start, length = nil)
@@ -1255,7 +1272,7 @@ module Oga
1255
1272
  #
1256
1273
  # @see [#on_call_string]
1257
1274
  # @param [Oga::XML::NodeSet] context
1258
- # @param [Oga::XPath::Node] expression
1275
+ # @param [AST::Node] expression
1259
1276
  # @return [Float]
1260
1277
  #
1261
1278
  def on_call_string_length(context, expression = nil)
@@ -1273,7 +1290,7 @@ module Oga
1273
1290
  # normalize-space(" fo o ") # => "fo o"
1274
1291
  #
1275
1292
  # @param [Oga::XML::NodeSet] context
1276
- # @param [Oga::XPath::Node] expression
1293
+ # @param [AST::Node] expression
1277
1294
  # @return [String]
1278
1295
  #
1279
1296
  def on_call_normalize_space(context, expression = nil)
@@ -1292,9 +1309,9 @@ module Oga
1292
1309
  # translate("bar", "abc", "ABC") # => "BAr"
1293
1310
  #
1294
1311
  # @param [Oga::XML::NodeSet] context
1295
- # @param [Oga::XPath::Node] input
1296
- # @param [Oga::XPath::Node] find
1297
- # @param [Oga::XPath::Node] replace
1312
+ # @param [AST::Node] input
1313
+ # @param [AST::Node] find
1314
+ # @param [AST::Node] replace
1298
1315
  # @return [String]
1299
1316
  #
1300
1317
  def on_call_translate(context, input, find, replace)
@@ -1325,7 +1342,7 @@ module Oga
1325
1342
  # The boolean `false` is returned for all other cases.
1326
1343
  #
1327
1344
  # @param [Oga::XML::NodeSet] context
1328
- # @param [Oga::XPath::Node] expression
1345
+ # @param [AST::Node] expression
1329
1346
  # @return [TrueClass|FalseClass]
1330
1347
  #
1331
1348
  def on_call_boolean(context, expression)
@@ -1349,7 +1366,7 @@ module Oga
1349
1366
  # `true` then this function returns `false` instead.
1350
1367
  #
1351
1368
  # @param [Oga::XML::NodeSet] context
1352
- # @param [Oga::XPath::Node] expression
1369
+ # @param [AST::Node] expression
1353
1370
  # @return [TrueClass|FalseClass]
1354
1371
  #
1355
1372
  def on_call_not(context, expression)
@@ -1361,7 +1378,7 @@ module Oga
1361
1378
  #
1362
1379
  # This function simply returns the boolean `true`.
1363
1380
  #
1364
- # @param [Oga::XPath::NodeSet] context
1381
+ # @param [AST::NodeSet] context
1365
1382
  # @return [TrueClass]
1366
1383
  #
1367
1384
  def on_call_true(context)
@@ -1373,7 +1390,7 @@ module Oga
1373
1390
  #
1374
1391
  # This function simply returns the boolean `false`.
1375
1392
  #
1376
- # @param [Oga::XPath::NodeSet] context
1393
+ # @param [AST::NodeSet] context
1377
1394
  # @return [FalseClass]
1378
1395
  #
1379
1396
  def on_call_false(context)
@@ -1391,7 +1408,7 @@ module Oga
1391
1408
  # such attribute).
1392
1409
  #
1393
1410
  # @param [Oga::XML::NodeSet] context
1394
- # @param [Oga::XPath::Node] language
1411
+ # @param [AST::Node] language
1395
1412
  # @return [TrueClass|FalseClass]
1396
1413
  #
1397
1414
  def on_call_lang(context, language)
@@ -1425,7 +1442,7 @@ module Oga
1425
1442
  # Using the expression `sum(root/*)` the return value would be `3.0`.
1426
1443
  #
1427
1444
  # @param [Oga::XML::NodeSet] context
1428
- # @param [Oga::XPath::Node] expression
1445
+ # @param [AST::Node] expression
1429
1446
  # @return [Float]
1430
1447
  #
1431
1448
  def on_call_sum(context, expression)
@@ -1450,7 +1467,7 @@ module Oga
1450
1467
  # and then returns that number as a float.
1451
1468
  #
1452
1469
  # @param [Oga::XML::NodeSet] context
1453
- # @param [Oga::XPath::Node] expression
1470
+ # @param [AST::Node] expression
1454
1471
  # @return [Float]
1455
1472
  #
1456
1473
  def on_call_floor(context, expression)
@@ -1466,7 +1483,7 @@ module Oga
1466
1483
  # and then returns that number as a float.
1467
1484
  #
1468
1485
  # @param [Oga::XML::NodeSet] context
1469
- # @param [Oga::XPath::Node] expression
1486
+ # @param [AST::Node] expression
1470
1487
  # @return [Float]
1471
1488
  #
1472
1489
  def on_call_ceiling(context, expression)
@@ -1482,7 +1499,7 @@ module Oga
1482
1499
  # then returns that number as a float.
1483
1500
  #
1484
1501
  # @param [Oga::XML::NodeSet] context
1485
- # @param [Oga::XPath::Node] expression
1502
+ # @param [AST::Node] expression
1486
1503
  # @return [Float]
1487
1504
  #
1488
1505
  def on_call_round(context, expression)
@@ -1494,7 +1511,7 @@ module Oga
1494
1511
  ##
1495
1512
  # Processes an `(int)` node.
1496
1513
  #
1497
- # @param [Oga::XPath::Node] ast_node
1514
+ # @param [AST::Node] ast_node
1498
1515
  # @param [Oga::XML::NodeSet] context
1499
1516
  # @return [Float]
1500
1517
  #
@@ -1505,7 +1522,7 @@ module Oga
1505
1522
  ##
1506
1523
  # Processes an `(float)` node.
1507
1524
  #
1508
- # @param [Oga::XPath::Node] ast_node
1525
+ # @param [AST::Node] ast_node
1509
1526
  # @param [Oga::XML::NodeSet] context
1510
1527
  # @return [Float]
1511
1528
  #
@@ -1516,7 +1533,7 @@ module Oga
1516
1533
  ##
1517
1534
  # Processes a `(string)` node.
1518
1535
  #
1519
- # @param [Oga::XPath::Node] ast_node
1536
+ # @param [AST::Node] ast_node
1520
1537
  # @param [Oga::XML::NodeSet] context
1521
1538
  # @return [String]
1522
1539
  #
@@ -1528,7 +1545,7 @@ module Oga
1528
1545
  # Processes a variable reference. If the variable is not defined an error
1529
1546
  # is raised.
1530
1547
  #
1531
- # @param [Oga::XPath::Node] ast_node
1548
+ # @param [AST::Node] ast_node
1532
1549
  # @param [Oga::XML::NodeSet] context
1533
1550
  # @return [Mixed]
1534
1551
  # @raise [RuntimeError]
@@ -1548,7 +1565,7 @@ module Oga
1548
1565
  # in the supplied node set, or the first node in the current context.
1549
1566
  #
1550
1567
  # @param [Oga::XML::NodeSet] context
1551
- # @param [Oga::XPath::Node] expression
1568
+ # @param [AST::Node] expression
1552
1569
  # @return [Oga::XML::Node]
1553
1570
  #
1554
1571
  def function_node(context, expression = nil)
@@ -1596,7 +1613,7 @@ module Oga
1596
1613
  end
1597
1614
 
1598
1615
  ##
1599
- # Checks if a given {Oga::XML::Node} instance matches a {Oga::XPath::Node}
1616
+ # Checks if a given {Oga::XML::Node} instance matches a `AST::Node`
1600
1617
  # instance.
1601
1618
  #
1602
1619
  # This method can use both "test" and "type-test" nodes. In case of
@@ -1614,7 +1631,7 @@ module Oga
1614
1631
  # For both the name and namespace a wildcard (`*`) can be used.
1615
1632
  #
1616
1633
  # @param [Oga::XML::Node] xml_node
1617
- # @param [Oga::XPath::Node] ast_node
1634
+ # @param [AST::Node] ast_node
1618
1635
  # @return [Oga::XML::NodeSet]
1619
1636
  #
1620
1637
  def node_matches?(xml_node, ast_node)
@@ -1645,7 +1662,7 @@ module Oga
1645
1662
 
1646
1663
  ##
1647
1664
  # @param [Oga::XML::Node] xml_node
1648
- # @param [Oga::XPath::Node] ast_node
1665
+ # @param [AST::Node] ast_node
1649
1666
  # @return [TrueClass|FalseClass]
1650
1667
  #
1651
1668
  def type_matches?(xml_node, ast_node)
@@ -1744,6 +1761,26 @@ module Oga
1744
1761
  def current_node_set
1745
1762
  return @node_sets.last
1746
1763
  end
1764
+
1765
+ ##
1766
+ # Returns the root node of `node`, or `node` itself if its a Document.
1767
+ #
1768
+ # @param [Oga::XML::Node|Oga::XML::Document] node
1769
+ # @return [Oga::XML::Node|Oga::XML::Document]
1770
+ #
1771
+ def root_node(node)
1772
+ return node.respond_to?(:root_node) ? node.root_node : node
1773
+ end
1774
+
1775
+ ##
1776
+ # Returns the parent node of `node`, or `node` itself if its a Document.
1777
+ #
1778
+ # @param [Oga::XML::Node|Oga::XML::Document] node
1779
+ # @return [Oga::XML::Node|Oga::XML::Document]
1780
+ #
1781
+ def parent_node(node)
1782
+ return node.respond_to?(:parent) ? node.parent : node
1783
+ end
1747
1784
  end # Evaluator
1748
1785
  end # XPath
1749
1786
  end # Oga