nokogiri 1.1.1-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.

Files changed (142) hide show
  1. data/History.ja.txt +99 -0
  2. data/History.txt +99 -0
  3. data/Manifest.txt +141 -0
  4. data/README.ja.txt +100 -0
  5. data/README.txt +109 -0
  6. data/Rakefile +354 -0
  7. data/ext/nokogiri/extconf.rb +93 -0
  8. data/ext/nokogiri/html_document.c +86 -0
  9. data/ext/nokogiri/html_document.h +10 -0
  10. data/ext/nokogiri/html_sax_parser.c +36 -0
  11. data/ext/nokogiri/html_sax_parser.h +11 -0
  12. data/ext/nokogiri/native.c +41 -0
  13. data/ext/nokogiri/native.h +50 -0
  14. data/ext/nokogiri/xml_cdata.c +44 -0
  15. data/ext/nokogiri/xml_cdata.h +9 -0
  16. data/ext/nokogiri/xml_comment.c +42 -0
  17. data/ext/nokogiri/xml_comment.h +9 -0
  18. data/ext/nokogiri/xml_document.c +206 -0
  19. data/ext/nokogiri/xml_document.h +10 -0
  20. data/ext/nokogiri/xml_dtd.c +121 -0
  21. data/ext/nokogiri/xml_dtd.h +8 -0
  22. data/ext/nokogiri/xml_io.c +17 -0
  23. data/ext/nokogiri/xml_io.h +9 -0
  24. data/ext/nokogiri/xml_node.c +727 -0
  25. data/ext/nokogiri/xml_node.h +13 -0
  26. data/ext/nokogiri/xml_node_set.c +118 -0
  27. data/ext/nokogiri/xml_node_set.h +9 -0
  28. data/ext/nokogiri/xml_reader.c +465 -0
  29. data/ext/nokogiri/xml_reader.h +10 -0
  30. data/ext/nokogiri/xml_sax_parser.c +201 -0
  31. data/ext/nokogiri/xml_sax_parser.h +10 -0
  32. data/ext/nokogiri/xml_syntax_error.c +199 -0
  33. data/ext/nokogiri/xml_syntax_error.h +11 -0
  34. data/ext/nokogiri/xml_text.c +40 -0
  35. data/ext/nokogiri/xml_text.h +9 -0
  36. data/ext/nokogiri/xml_xpath.c +53 -0
  37. data/ext/nokogiri/xml_xpath.h +11 -0
  38. data/ext/nokogiri/xml_xpath_context.c +214 -0
  39. data/ext/nokogiri/xml_xpath_context.h +9 -0
  40. data/ext/nokogiri/xslt_stylesheet.c +123 -0
  41. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  42. data/lib/action-nokogiri.rb +30 -0
  43. data/lib/nokogiri.rb +72 -0
  44. data/lib/nokogiri/css.rb +25 -0
  45. data/lib/nokogiri/css/generated_parser.rb +721 -0
  46. data/lib/nokogiri/css/generated_tokenizer.rb +159 -0
  47. data/lib/nokogiri/css/node.rb +97 -0
  48. data/lib/nokogiri/css/parser.rb +64 -0
  49. data/lib/nokogiri/css/parser.y +216 -0
  50. data/lib/nokogiri/css/syntax_error.rb +6 -0
  51. data/lib/nokogiri/css/tokenizer.rb +9 -0
  52. data/lib/nokogiri/css/tokenizer.rex +63 -0
  53. data/lib/nokogiri/css/xpath_visitor.rb +168 -0
  54. data/lib/nokogiri/decorators.rb +2 -0
  55. data/lib/nokogiri/decorators/hpricot.rb +3 -0
  56. data/lib/nokogiri/decorators/hpricot/node.rb +56 -0
  57. data/lib/nokogiri/decorators/hpricot/node_set.rb +54 -0
  58. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +28 -0
  59. data/lib/nokogiri/decorators/slop.rb +31 -0
  60. data/lib/nokogiri/hpricot.rb +51 -0
  61. data/lib/nokogiri/html.rb +105 -0
  62. data/lib/nokogiri/html/builder.rb +9 -0
  63. data/lib/nokogiri/html/document.rb +9 -0
  64. data/lib/nokogiri/html/sax/parser.rb +21 -0
  65. data/lib/nokogiri/version.rb +3 -0
  66. data/lib/nokogiri/xml.rb +83 -0
  67. data/lib/nokogiri/xml/after_handler.rb +18 -0
  68. data/lib/nokogiri/xml/attr.rb +10 -0
  69. data/lib/nokogiri/xml/before_handler.rb +33 -0
  70. data/lib/nokogiri/xml/builder.rb +84 -0
  71. data/lib/nokogiri/xml/cdata.rb +9 -0
  72. data/lib/nokogiri/xml/comment.rb +6 -0
  73. data/lib/nokogiri/xml/document.rb +55 -0
  74. data/lib/nokogiri/xml/dtd.rb +6 -0
  75. data/lib/nokogiri/xml/element.rb +6 -0
  76. data/lib/nokogiri/xml/entity_declaration.rb +9 -0
  77. data/lib/nokogiri/xml/node.rb +333 -0
  78. data/lib/nokogiri/xml/node_set.rb +197 -0
  79. data/lib/nokogiri/xml/notation.rb +6 -0
  80. data/lib/nokogiri/xml/reader.rb +20 -0
  81. data/lib/nokogiri/xml/sax.rb +9 -0
  82. data/lib/nokogiri/xml/sax/document.rb +59 -0
  83. data/lib/nokogiri/xml/sax/parser.rb +37 -0
  84. data/lib/nokogiri/xml/syntax_error.rb +21 -0
  85. data/lib/nokogiri/xml/text.rb +6 -0
  86. data/lib/nokogiri/xml/xpath.rb +10 -0
  87. data/lib/nokogiri/xml/xpath/syntax_error.rb +8 -0
  88. data/lib/nokogiri/xml/xpath_context.rb +14 -0
  89. data/lib/nokogiri/xslt.rb +28 -0
  90. data/lib/nokogiri/xslt/stylesheet.rb +6 -0
  91. data/test/css/test_nthiness.rb +159 -0
  92. data/test/css/test_parser.rb +237 -0
  93. data/test/css/test_tokenizer.rb +162 -0
  94. data/test/css/test_xpath_visitor.rb +64 -0
  95. data/test/files/dont_hurt_em_why.xml +422 -0
  96. data/test/files/exslt.xml +8 -0
  97. data/test/files/exslt.xslt +35 -0
  98. data/test/files/staff.xml +59 -0
  99. data/test/files/staff.xslt +32 -0
  100. data/test/files/tlm.html +850 -0
  101. data/test/helper.rb +78 -0
  102. data/test/hpricot/files/basic.xhtml +17 -0
  103. data/test/hpricot/files/boingboing.html +2266 -0
  104. data/test/hpricot/files/cy0.html +3653 -0
  105. data/test/hpricot/files/immob.html +400 -0
  106. data/test/hpricot/files/pace_application.html +1320 -0
  107. data/test/hpricot/files/tenderlove.html +16 -0
  108. data/test/hpricot/files/uswebgen.html +220 -0
  109. data/test/hpricot/files/utf8.html +1054 -0
  110. data/test/hpricot/files/week9.html +1723 -0
  111. data/test/hpricot/files/why.xml +19 -0
  112. data/test/hpricot/load_files.rb +11 -0
  113. data/test/hpricot/test_alter.rb +67 -0
  114. data/test/hpricot/test_builder.rb +27 -0
  115. data/test/hpricot/test_parser.rb +426 -0
  116. data/test/hpricot/test_paths.rb +15 -0
  117. data/test/hpricot/test_preserved.rb +77 -0
  118. data/test/hpricot/test_xml.rb +30 -0
  119. data/test/html/sax/test_parser.rb +27 -0
  120. data/test/html/test_builder.rb +89 -0
  121. data/test/html/test_document.rb +150 -0
  122. data/test/html/test_node.rb +21 -0
  123. data/test/test_convert_xpath.rb +185 -0
  124. data/test/test_css_cache.rb +57 -0
  125. data/test/test_gc.rb +15 -0
  126. data/test/test_memory_leak.rb +38 -0
  127. data/test/test_nokogiri.rb +97 -0
  128. data/test/test_reader.rb +222 -0
  129. data/test/test_xslt_transforms.rb +93 -0
  130. data/test/xml/sax/test_parser.rb +95 -0
  131. data/test/xml/test_attr.rb +15 -0
  132. data/test/xml/test_builder.rb +16 -0
  133. data/test/xml/test_cdata.rb +18 -0
  134. data/test/xml/test_comment.rb +16 -0
  135. data/test/xml/test_document.rb +195 -0
  136. data/test/xml/test_dtd.rb +43 -0
  137. data/test/xml/test_node.rb +394 -0
  138. data/test/xml/test_node_set.rb +143 -0
  139. data/test/xml/test_text.rb +13 -0
  140. data/test/xml/test_xpath.rb +105 -0
  141. data/vendor/hoe.rb +1020 -0
  142. metadata +233 -0
@@ -0,0 +1,6 @@
1
+ module Nokogiri
2
+ module CSS
3
+ class SyntaxError < ::SyntaxError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module Nokogiri
2
+ module CSS
3
+ class Tokenizer < GeneratedTokenizer
4
+ def scan(str)
5
+ scan_evaluate(str)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ module Nokogiri
2
+ module CSS
3
+ class GeneratedTokenizer < GeneratedParser
4
+
5
+ macro
6
+ nl \n|\r\n|\r|\f
7
+ w [\s\r\n\f]*
8
+ nonascii [^\\\\0-\\\\177]
9
+ num -?([0-9]+|[0-9]*\.[0-9]+)
10
+ unicode \\\\\\\\\[0-9a-f]{1,6}(\r\n|[\s\n\r\t\f])?
11
+
12
+ escape {unicode}|\\\\\\\[^\n\r\f0-9a-f]
13
+ nmchar [_a-z0-9-]|{nonascii}|{escape}
14
+ nmstart [_a-z]|{nonascii}|{escape}
15
+ ident [-]?({nmstart})({nmchar})*
16
+ name ({nmchar})+
17
+ string1 "([^\n\r\f"]|\\{nl}|{nonascii}|{escape})*"
18
+ string2 '([^\n\r\f']|\\{nl}|{nonascii}|{escape})*'
19
+ string {string1}|{string2}
20
+ invalid1 \"([^\n\r\f\\"]|\\{nl}|{nonascii}|{escape})*
21
+ invalid2 \'([^\n\r\f\\']|\\{nl}|{nonascii}|{escape})*
22
+ invalid {invalid1}|{invalid2}
23
+ Comment \/\*(.|[\r\n])*?\*\/
24
+
25
+ rule
26
+
27
+ # [:state] pattern [actions]
28
+
29
+ ~= { [:INCLUDES, text] }
30
+ \|= { [:DASHMATCH, text] }
31
+ \^= { [:PREFIXMATCH, text] }
32
+ \$= { [:SUFFIXMATCH, text] }
33
+ \*= { [:SUBSTRINGMATCH, text] }
34
+ != { [:NOT_EQUAL, text] }
35
+ {ident}\(\s* { [:FUNCTION, text] }
36
+ @{ident} { [:IDENT, text] }
37
+ {ident} { [:IDENT, text] }
38
+ {num} { [:NUMBER, text] }
39
+ \#{name} { [:HASH, text] }
40
+ {w}\+ { [:PLUS, text] }
41
+ {w}> { [:GREATER, text] }
42
+ {w}, { [:COMMA, text] }
43
+ {w}~ { [:TILDE, text] }
44
+ \:not\( { [:NOT, text] }
45
+ @{ident} { [:ATKEYWORD, text] }
46
+ {num}% { [:PERCENTAGE, text] }
47
+ {num}{ident} { [:DIMENSION, text] }
48
+ <!-- { [:CDO, text] }
49
+ --> { [:CDC, text] }
50
+ {w}\/\/ { [:DOUBLESLASH, text] }
51
+ {w}\/ { [:SLASH, text] }
52
+
53
+ U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})? {[:UNICODE_RANGE, text] }
54
+
55
+ {Comment} /* ignore comments */
56
+ [\s\t\r\n\f]+ { [:S, text] }
57
+ [\.*:\[\]=\)] { [text, text] }
58
+ {string} { [:STRING, text] }
59
+ {invalid} { [:INVALID, text] }
60
+ . { [text, text] }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,168 @@
1
+ module Nokogiri
2
+ module CSS
3
+ class XPathVisitor
4
+ def visit_function node
5
+ # note that nth-child and nth-last-child are preprocessed in css/node.rb.
6
+ msg = :"visit_function_#{node.value.first.gsub(/[(]/, '')}"
7
+ return self.send(msg, node) if self.respond_to?(msg)
8
+
9
+ case node.value.first
10
+ when /^text\(/
11
+ 'child::text()'
12
+ when /^self\(/
13
+ "self::#{node.value[1]}"
14
+ when /^(eq|nth|nth-of-type|nth-child)\(/
15
+ if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
16
+ an_plus_b(node.value[1])
17
+ else
18
+ "position() = " + node.value[1]
19
+ end
20
+ when /^(first|first-of-type)\(/
21
+ "position() = 1"
22
+ when /^(last|last-of-type)\(/
23
+ "position() = last()"
24
+ when /^(nth-last-child|nth-last-of-type)\(/
25
+ "position() = last() - #{node.value[1]}"
26
+ when /^contains\(/
27
+ "contains(., #{node.value[1]})"
28
+ when /^gt\(/
29
+ "position() > #{node.value[1]}"
30
+ when /^only-child\(/
31
+ "last() = 1"
32
+ when /^comment\(/
33
+ "comment()"
34
+ else
35
+ args = ['.'] + node.value[1..-1]
36
+ "#{node.value.first}#{args.join(', ')})"
37
+ end
38
+ end
39
+
40
+ def visit_not node
41
+ 'not(' + node.value.first.accept(self) + ')'
42
+ end
43
+
44
+ def visit_preceding_selector node
45
+ node.value.last.accept(self) +
46
+ '[preceding-sibling::' +
47
+ node.value.first.accept(self) +
48
+ ']'
49
+ end
50
+
51
+ def visit_direct_adjacent_selector node
52
+ node.value.first.accept(self) +
53
+ "/following-sibling::*[1]/self::" +
54
+ node.value.last.accept(self)
55
+ end
56
+
57
+ def visit_id node
58
+ node.value.first =~ /^#(.*)$/
59
+ "@id = '#{$1}'"
60
+ end
61
+
62
+ def visit_attribute_condition node
63
+ attribute = if (node.value.first.type == :FUNCTION) or (node.value.first.value.first =~ /::/)
64
+ ''
65
+ else
66
+ '@'
67
+ end
68
+ attribute += node.value.first.accept(self)
69
+
70
+ # Support non-standard css
71
+ attribute.gsub!(/^@@/, '@')
72
+
73
+ return attribute unless node.value.length == 3
74
+
75
+ value = node.value.last
76
+ value = "'#{value}'" if value !~ /^['"]/
77
+
78
+ case node.value[1]
79
+ when '*='
80
+ "contains(#{attribute}, #{value})"
81
+ when '^='
82
+ "starts-with(#{attribute}, #{value})"
83
+ when '|='
84
+ "#{attribute} = #{value} or starts-with(#{attribute}, concat(#{value}, '-'))"
85
+ when '~='
86
+ "contains(concat(\" \", #{attribute}, \" \"),concat(\" \", #{value}, \" \"))"
87
+ when '$='
88
+ "substring(#{attribute}, string-length(#{attribute}) - " +
89
+ "string-length(#{value}) + 1, string-length(#{value})) = #{value}"
90
+ else
91
+ attribute + " #{node.value[1]} " + "#{value}"
92
+ end
93
+ end
94
+
95
+ def visit_pseudo_class node
96
+ if node.value.first.is_a?(Nokogiri::CSS::Node) and node.value.first.type == :FUNCTION
97
+ node.value.first.accept(self)
98
+ else
99
+ msg = :"visit_pseudo_class_#{node.value.first.gsub(/[(]/, '')}"
100
+ return self.send(msg, node) if self.respond_to?(msg)
101
+
102
+ case node.value.first
103
+ when "first" then "position() = 1"
104
+ when "last" then "position() = last()"
105
+ when "first-of-type" then "position() = 1"
106
+ when "last-of-type" then "position() = last()"
107
+ when "only-of-type" then "last() = 1"
108
+ when "empty" then "not(node())"
109
+ when "parent" then "node()"
110
+ when "root" then "not(parent::*)"
111
+ else
112
+ node.value.first + "(.)"
113
+ end
114
+ end
115
+ end
116
+
117
+ def visit_class_condition node
118
+ "contains(concat(' ', @class, ' '), ' #{node.value.first} ')"
119
+ end
120
+
121
+ def visit_combinator node
122
+ node.value.first.accept(self) + ' and ' +
123
+ node.value.last.accept(self)
124
+ end
125
+
126
+ def visit_conditional_selector node
127
+ node.value.first.accept(self) + '[' +
128
+ node.value.last.accept(self) + ']'
129
+ end
130
+
131
+ def visit_descendant_selector node
132
+ node.value.first.accept(self) +
133
+ '//' +
134
+ node.value.last.accept(self)
135
+ end
136
+
137
+ def visit_child_selector node
138
+ node.value.first.accept(self) +
139
+ '/' +
140
+ node.value.last.accept(self)
141
+ end
142
+
143
+ def visit_element_name node
144
+ node.value.first
145
+ end
146
+
147
+ def accept node
148
+ node.accept(self)
149
+ end
150
+
151
+ private
152
+ def an_plus_b node
153
+ raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
154
+
155
+ a = node.value[0].to_i
156
+ b = node.value[3].to_i
157
+
158
+ if (b == 0)
159
+ return "(position() mod #{a}) = 0"
160
+ else
161
+ compare = (a < 0) ? "<=" : ">="
162
+ return "(position() #{compare} #{b}) and (((position()-#{b}) mod #{a.abs}) = 0)"
163
+ end
164
+ end
165
+
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,2 @@
1
+ require 'nokogiri/decorators/hpricot'
2
+ require 'nokogiri/decorators/slop'
@@ -0,0 +1,3 @@
1
+ require 'nokogiri/decorators/hpricot/node'
2
+ require 'nokogiri/decorators/hpricot/node_set'
3
+ require 'nokogiri/decorators/hpricot/xpath_visitor'
@@ -0,0 +1,56 @@
1
+ module Nokogiri
2
+ module Decorators
3
+ module Hpricot
4
+ module Node
5
+ def search *paths
6
+ ns = paths.last.is_a?(Hash) ? paths.pop : {}
7
+ converted = paths.map { |path|
8
+ convert_to_xpath(path)
9
+ }.flatten.uniq
10
+
11
+ super(*converted + [ns])
12
+ end
13
+ def /(path); search(path) end
14
+
15
+ def xpath *args
16
+ return super if args.length > 0
17
+ path
18
+ end
19
+
20
+ def raw_attributes; self end
21
+
22
+ def get_element_by_id element_id
23
+ search("//*[@id='#{element_id}']").first
24
+ end
25
+
26
+ def get_elements_by_tag_name tag
27
+ search("//#{tag}")
28
+ end
29
+
30
+ def convert_to_xpath(rule)
31
+ rule = rule.to_s
32
+ case rule
33
+ when %r{^//}
34
+ [".#{Hpricot::XPathVisitor.xpath_namespace_helper(rule)}"]
35
+ when %r{^/}
36
+ [Hpricot::XPathVisitor.xpath_namespace_helper(rule)]
37
+ when %r{^.//}
38
+ [Hpricot::XPathVisitor.xpath_namespace_helper(rule)]
39
+ else
40
+ visitor = CSS::XPathVisitor.new
41
+ visitor.extend(Hpricot::XPathVisitor)
42
+ CSS.xpath_for(rule, :prefix => ".//", :visitor => visitor)
43
+ end
44
+ end
45
+
46
+ def target
47
+ name
48
+ end
49
+
50
+ def to_original_html
51
+ to_html
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,54 @@
1
+ module Nokogiri
2
+ module Decorators
3
+ module Hpricot
4
+ module NodeSet
5
+
6
+ # Select nodes matching the supplied rule.
7
+ # Note that positional rules (like <tt>:nth()</tt>) aren't currently supported.
8
+ #
9
+ # example:
10
+ # node_set.filter('.ohmy') # selects nodes from the set with class "ohmy"
11
+ # node_set.filter('a#link2') # selects nodes from the set with child node <a id='link2'>
12
+ # node_set.filter('a[@id="link2"]') # selects nodes from the set with child node <a id='link2'>
13
+ def filter(rule)
14
+ filter_transformer( lambda {|j| j}, rule ) # identity transformer
15
+ end
16
+
17
+ # The complement to filter, select nodes <em>not</em> matching the supplied rule.
18
+ # Note that positional rules (like <tt>:nth()</tt>) aren't currently supported.
19
+ #
20
+ # See filter for examples.
21
+ #
22
+ # Also note that you can pass a XML::Node object instead of a
23
+ # rule to remove that object from the node set (if it is
24
+ # present):
25
+ # node_set.not(node_to_exclude) # selects all nodes EXCEPT node_to_exclude
26
+ #
27
+ def not(rule)
28
+ filter_transformer( lambda {|j| !j}, rule ) # negation transformer
29
+ end
30
+
31
+ private
32
+ def filter_transformer(transformer, rule)
33
+ sub_set = XML::NodeSet.new(document)
34
+ document.decorate(sub_set)
35
+
36
+ if rule.is_a?(XML::Node)
37
+ each { |node| sub_set << node if transformer.call(node == rule) }
38
+ return sub_set
39
+ end
40
+
41
+ ctx = CSS::Parser.parse(rule.to_s)
42
+ visitor = CSS::XPathVisitor.new
43
+ visitor.extend(Hpricot::XPathVisitor)
44
+ each do |node|
45
+ if transformer.call(node.at(".//self::" + visitor.accept(ctx.first)))
46
+ sub_set << node
47
+ end
48
+ end
49
+ sub_set
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,28 @@
1
+ module Nokogiri
2
+ module Decorators
3
+ module Hpricot
4
+ ####
5
+ # This mixin does custom adjustments to deal with _whyML
6
+ module XPathVisitor
7
+ def visit_attribute_condition node
8
+ unless (node.value.first.type == :FUNCTION) or (node.value.first.value.first =~ /^@/)
9
+ node.value.first.value[0] = "child::" +
10
+ node.value.first.value[0]
11
+ end
12
+ super(node).gsub(/child::text\(\)/, 'normalize-space(child::text())')
13
+ end
14
+
15
+ # take a path like '//t:sam' and convert to xpath "*[name()='t:sam']"
16
+ def self.xpath_namespace_helper rule
17
+ rule.split(/\//).collect do |tag|
18
+ if match = tag.match(/^(\w+:\w+)(.*)/)
19
+ "*[name()='#{match[1]}']#{match[2]}"
20
+ else
21
+ tag
22
+ end
23
+ end.join("/")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module Nokogiri
2
+ module Decorators
3
+ ###
4
+ # The Slop decorator implements method missing such that a methods may be
5
+ # used instead of XPath or CSS. See Nokogiri.Slop
6
+ module Slop
7
+ def method_missing name, *args, &block
8
+ if args.empty?
9
+ list = xpath("./#{name}")
10
+ elsif args.first.is_a? Hash
11
+ hash = args.first
12
+ if hash[:css]
13
+ list = css("#{name}#{hash[:css]}")
14
+ elsif hash[:xpath]
15
+ conds = Array(hash[:xpath]).join(' and ')
16
+ list = xpath("./#{name}[#{conds}]")
17
+ end
18
+ else
19
+ CSS::Parser.without_cache do
20
+ list = xpath(
21
+ *CSS.xpath_for("#{name}#{args.first}", :prefix => "./")
22
+ )
23
+ end
24
+ end
25
+
26
+ super if list.empty?
27
+ list.length == 1 ? list.first : list
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ require 'nokogiri'
2
+
3
+ module Nokogiri
4
+ module Hpricot
5
+ STag = String
6
+ Elem = XML::Node
7
+ NamedCharacters = Nokogiri::HTML::NamedCharacters
8
+ class << self
9
+ def parse(*args)
10
+ doc = Nokogiri.parse(*args)
11
+ add_decorators(doc)
12
+ end
13
+
14
+ def XML(string)
15
+ doc = Nokogiri::XML.parse(string)
16
+ add_decorators(doc)
17
+ end
18
+
19
+ def HTML(string)
20
+ doc = Nokogiri::HTML.parse(string)
21
+ add_decorators(doc)
22
+ end
23
+
24
+ def make string
25
+ doc = XML::Document.new
26
+ ns = XML::NodeSet.new(doc)
27
+ ns << XML::Text.new(string, doc)
28
+ ns
29
+ end
30
+
31
+ def add_decorators(doc)
32
+ doc.decorators(XML::Node) << Decorators::Hpricot::Node
33
+ doc.decorators(XML::NodeSet) << Decorators::Hpricot::NodeSet
34
+ doc.decorate!
35
+ doc
36
+ end
37
+ end
38
+ end
39
+
40
+ class << self
41
+ def Hpricot(*args, &block)
42
+ if block_given?
43
+ builder = Nokogiri::HTML::Builder.new(&block)
44
+ Nokogiri::Hpricot.add_decorators(builder.doc)
45
+ else
46
+ doc = Nokogiri.parse(*args)
47
+ Nokogiri::Hpricot.add_decorators(doc)
48
+ end
49
+ end
50
+ end
51
+ end