nokogiri 1.3.0-x86-mswin32

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 (256) hide show
  1. data/.autotest +27 -0
  2. data/CHANGELOG.ja.rdoc +233 -0
  3. data/CHANGELOG.rdoc +222 -0
  4. data/Manifest.txt +247 -0
  5. data/README.ja.rdoc +103 -0
  6. data/README.rdoc +117 -0
  7. data/Rakefile +205 -0
  8. data/bin/nokogiri +47 -0
  9. data/ext/nokogiri/extconf.rb +89 -0
  10. data/ext/nokogiri/html_document.c +183 -0
  11. data/ext/nokogiri/html_document.h +10 -0
  12. data/ext/nokogiri/html_element_description.c +272 -0
  13. data/ext/nokogiri/html_element_description.h +10 -0
  14. data/ext/nokogiri/html_entity_lookup.c +30 -0
  15. data/ext/nokogiri/html_entity_lookup.h +8 -0
  16. data/ext/nokogiri/html_sax_parser.c +57 -0
  17. data/ext/nokogiri/html_sax_parser.h +11 -0
  18. data/ext/nokogiri/iconv.dll +0 -0
  19. data/ext/nokogiri/libexslt.dll +0 -0
  20. data/ext/nokogiri/libxml2.dll +0 -0
  21. data/ext/nokogiri/libxslt.dll +0 -0
  22. data/ext/nokogiri/nokogiri.c +81 -0
  23. data/ext/nokogiri/nokogiri.h +149 -0
  24. data/ext/nokogiri/xml_attr.c +92 -0
  25. data/ext/nokogiri/xml_attr.h +9 -0
  26. data/ext/nokogiri/xml_cdata.c +53 -0
  27. data/ext/nokogiri/xml_cdata.h +9 -0
  28. data/ext/nokogiri/xml_comment.c +51 -0
  29. data/ext/nokogiri/xml_comment.h +9 -0
  30. data/ext/nokogiri/xml_document.c +308 -0
  31. data/ext/nokogiri/xml_document.h +21 -0
  32. data/ext/nokogiri/xml_document_fragment.c +48 -0
  33. data/ext/nokogiri/xml_document_fragment.h +10 -0
  34. data/ext/nokogiri/xml_dtd.c +102 -0
  35. data/ext/nokogiri/xml_dtd.h +8 -0
  36. data/ext/nokogiri/xml_entity_reference.c +50 -0
  37. data/ext/nokogiri/xml_entity_reference.h +9 -0
  38. data/ext/nokogiri/xml_io.c +24 -0
  39. data/ext/nokogiri/xml_io.h +10 -0
  40. data/ext/nokogiri/xml_namespace.c +69 -0
  41. data/ext/nokogiri/xml_namespace.h +12 -0
  42. data/ext/nokogiri/xml_node.c +928 -0
  43. data/ext/nokogiri/xml_node.h +14 -0
  44. data/ext/nokogiri/xml_node_set.c +386 -0
  45. data/ext/nokogiri/xml_node_set.h +9 -0
  46. data/ext/nokogiri/xml_processing_instruction.c +54 -0
  47. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  48. data/ext/nokogiri/xml_reader.c +572 -0
  49. data/ext/nokogiri/xml_reader.h +10 -0
  50. data/ext/nokogiri/xml_relax_ng.c +106 -0
  51. data/ext/nokogiri/xml_relax_ng.h +9 -0
  52. data/ext/nokogiri/xml_sax_parser.c +336 -0
  53. data/ext/nokogiri/xml_sax_parser.h +10 -0
  54. data/ext/nokogiri/xml_sax_push_parser.c +86 -0
  55. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  56. data/ext/nokogiri/xml_schema.c +107 -0
  57. data/ext/nokogiri/xml_schema.h +9 -0
  58. data/ext/nokogiri/xml_syntax_error.c +203 -0
  59. data/ext/nokogiri/xml_syntax_error.h +12 -0
  60. data/ext/nokogiri/xml_text.c +47 -0
  61. data/ext/nokogiri/xml_text.h +9 -0
  62. data/ext/nokogiri/xml_xpath.c +53 -0
  63. data/ext/nokogiri/xml_xpath.h +11 -0
  64. data/ext/nokogiri/xml_xpath_context.c +252 -0
  65. data/ext/nokogiri/xml_xpath_context.h +9 -0
  66. data/ext/nokogiri/xslt_stylesheet.c +131 -0
  67. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  68. data/ext/nokogiri/zlib1.dll +0 -0
  69. data/lib/action-nokogiri.rb +36 -0
  70. data/lib/nokogiri.rb +110 -0
  71. data/lib/nokogiri/1.8/nokogiri.so +0 -0
  72. data/lib/nokogiri/1.9/nokogiri.so +0 -0
  73. data/lib/nokogiri/css.rb +25 -0
  74. data/lib/nokogiri/css/generated_parser.rb +748 -0
  75. data/lib/nokogiri/css/generated_tokenizer.rb +144 -0
  76. data/lib/nokogiri/css/node.rb +107 -0
  77. data/lib/nokogiri/css/parser.rb +82 -0
  78. data/lib/nokogiri/css/parser.y +227 -0
  79. data/lib/nokogiri/css/syntax_error.rb +7 -0
  80. data/lib/nokogiri/css/tokenizer.rb +11 -0
  81. data/lib/nokogiri/css/tokenizer.rex +54 -0
  82. data/lib/nokogiri/css/xpath_visitor.rb +172 -0
  83. data/lib/nokogiri/decorators.rb +2 -0
  84. data/lib/nokogiri/decorators/hpricot.rb +3 -0
  85. data/lib/nokogiri/decorators/hpricot/node.rb +56 -0
  86. data/lib/nokogiri/decorators/hpricot/node_set.rb +54 -0
  87. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +30 -0
  88. data/lib/nokogiri/decorators/slop.rb +33 -0
  89. data/lib/nokogiri/ffi/html/document.rb +37 -0
  90. data/lib/nokogiri/ffi/html/element_description.rb +85 -0
  91. data/lib/nokogiri/ffi/html/entity_lookup.rb +16 -0
  92. data/lib/nokogiri/ffi/html/sax/parser.rb +21 -0
  93. data/lib/nokogiri/ffi/io_callbacks.rb +32 -0
  94. data/lib/nokogiri/ffi/libxml.rb +314 -0
  95. data/lib/nokogiri/ffi/structs/common_node.rb +26 -0
  96. data/lib/nokogiri/ffi/structs/html_elem_desc.rb +24 -0
  97. data/lib/nokogiri/ffi/structs/html_entity_desc.rb +13 -0
  98. data/lib/nokogiri/ffi/structs/xml_alloc.rb +16 -0
  99. data/lib/nokogiri/ffi/structs/xml_attr.rb +19 -0
  100. data/lib/nokogiri/ffi/structs/xml_buffer.rb +16 -0
  101. data/lib/nokogiri/ffi/structs/xml_document.rb +108 -0
  102. data/lib/nokogiri/ffi/structs/xml_dtd.rb +26 -0
  103. data/lib/nokogiri/ffi/structs/xml_node.rb +28 -0
  104. data/lib/nokogiri/ffi/structs/xml_node_set.rb +53 -0
  105. data/lib/nokogiri/ffi/structs/xml_notation.rb +11 -0
  106. data/lib/nokogiri/ffi/structs/xml_ns.rb +15 -0
  107. data/lib/nokogiri/ffi/structs/xml_relax_ng.rb +14 -0
  108. data/lib/nokogiri/ffi/structs/xml_sax_handler.rb +51 -0
  109. data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +14 -0
  110. data/lib/nokogiri/ffi/structs/xml_schema.rb +13 -0
  111. data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +31 -0
  112. data/lib/nokogiri/ffi/structs/xml_text_reader.rb +12 -0
  113. data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +37 -0
  114. data/lib/nokogiri/ffi/structs/xml_xpath_object.rb +35 -0
  115. data/lib/nokogiri/ffi/structs/xml_xpath_parser_context.rb +20 -0
  116. data/lib/nokogiri/ffi/structs/xslt_stylesheet.rb +13 -0
  117. data/lib/nokogiri/ffi/xml/attr.rb +41 -0
  118. data/lib/nokogiri/ffi/xml/cdata.rb +19 -0
  119. data/lib/nokogiri/ffi/xml/comment.rb +18 -0
  120. data/lib/nokogiri/ffi/xml/document.rb +107 -0
  121. data/lib/nokogiri/ffi/xml/document_fragment.rb +26 -0
  122. data/lib/nokogiri/ffi/xml/dtd.rb +42 -0
  123. data/lib/nokogiri/ffi/xml/entity_reference.rb +19 -0
  124. data/lib/nokogiri/ffi/xml/namespace.rb +38 -0
  125. data/lib/nokogiri/ffi/xml/node.rb +380 -0
  126. data/lib/nokogiri/ffi/xml/node_set.rb +130 -0
  127. data/lib/nokogiri/ffi/xml/processing_instruction.rb +20 -0
  128. data/lib/nokogiri/ffi/xml/reader.rb +217 -0
  129. data/lib/nokogiri/ffi/xml/relax_ng.rb +51 -0
  130. data/lib/nokogiri/ffi/xml/sax/parser.rb +148 -0
  131. data/lib/nokogiri/ffi/xml/sax/push_parser.rb +38 -0
  132. data/lib/nokogiri/ffi/xml/schema.rb +55 -0
  133. data/lib/nokogiri/ffi/xml/syntax_error.rb +76 -0
  134. data/lib/nokogiri/ffi/xml/text.rb +18 -0
  135. data/lib/nokogiri/ffi/xml/xpath.rb +19 -0
  136. data/lib/nokogiri/ffi/xml/xpath_context.rb +135 -0
  137. data/lib/nokogiri/ffi/xslt/stylesheet.rb +47 -0
  138. data/lib/nokogiri/hpricot.rb +62 -0
  139. data/lib/nokogiri/html.rb +34 -0
  140. data/lib/nokogiri/html/builder.rb +35 -0
  141. data/lib/nokogiri/html/document.rb +71 -0
  142. data/lib/nokogiri/html/document_fragment.rb +15 -0
  143. data/lib/nokogiri/html/element_description.rb +23 -0
  144. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  145. data/lib/nokogiri/html/sax/parser.rb +47 -0
  146. data/lib/nokogiri/nokogiri.rb +1 -0
  147. data/lib/nokogiri/syntax_error.rb +4 -0
  148. data/lib/nokogiri/version.rb +29 -0
  149. data/lib/nokogiri/version_warning.rb +11 -0
  150. data/lib/nokogiri/xml.rb +62 -0
  151. data/lib/nokogiri/xml/attr.rb +9 -0
  152. data/lib/nokogiri/xml/builder.rb +254 -0
  153. data/lib/nokogiri/xml/cdata.rb +11 -0
  154. data/lib/nokogiri/xml/document.rb +100 -0
  155. data/lib/nokogiri/xml/document_fragment.rb +49 -0
  156. data/lib/nokogiri/xml/dtd.rb +11 -0
  157. data/lib/nokogiri/xml/entity_declaration.rb +11 -0
  158. data/lib/nokogiri/xml/fragment_handler.rb +55 -0
  159. data/lib/nokogiri/xml/namespace.rb +7 -0
  160. data/lib/nokogiri/xml/node.rb +745 -0
  161. data/lib/nokogiri/xml/node/save_options.rb +42 -0
  162. data/lib/nokogiri/xml/node_set.rb +238 -0
  163. data/lib/nokogiri/xml/notation.rb +6 -0
  164. data/lib/nokogiri/xml/parse_options.rb +80 -0
  165. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  166. data/lib/nokogiri/xml/reader.rb +66 -0
  167. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  168. data/lib/nokogiri/xml/sax.rb +3 -0
  169. data/lib/nokogiri/xml/sax/document.rb +143 -0
  170. data/lib/nokogiri/xml/sax/parser.rb +101 -0
  171. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  172. data/lib/nokogiri/xml/schema.rb +65 -0
  173. data/lib/nokogiri/xml/syntax_error.rb +34 -0
  174. data/lib/nokogiri/xml/xpath.rb +10 -0
  175. data/lib/nokogiri/xml/xpath/syntax_error.rb +8 -0
  176. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  177. data/lib/nokogiri/xslt.rb +48 -0
  178. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  179. data/lib/xsd/xmlparser/nokogiri.rb +64 -0
  180. data/tasks/test.rb +161 -0
  181. data/test/css/test_nthiness.rb +160 -0
  182. data/test/css/test_parser.rb +277 -0
  183. data/test/css/test_tokenizer.rb +176 -0
  184. data/test/css/test_xpath_visitor.rb +76 -0
  185. data/test/ffi/test_document.rb +35 -0
  186. data/test/files/address_book.rlx +12 -0
  187. data/test/files/address_book.xml +10 -0
  188. data/test/files/dont_hurt_em_why.xml +422 -0
  189. data/test/files/exslt.xml +8 -0
  190. data/test/files/exslt.xslt +35 -0
  191. data/test/files/po.xml +32 -0
  192. data/test/files/po.xsd +66 -0
  193. data/test/files/staff.xml +59 -0
  194. data/test/files/staff.xslt +32 -0
  195. data/test/files/tlm.html +850 -0
  196. data/test/helper.rb +123 -0
  197. data/test/hpricot/files/basic.xhtml +17 -0
  198. data/test/hpricot/files/boingboing.html +2266 -0
  199. data/test/hpricot/files/cy0.html +3653 -0
  200. data/test/hpricot/files/immob.html +400 -0
  201. data/test/hpricot/files/pace_application.html +1320 -0
  202. data/test/hpricot/files/tenderlove.html +16 -0
  203. data/test/hpricot/files/uswebgen.html +220 -0
  204. data/test/hpricot/files/utf8.html +1054 -0
  205. data/test/hpricot/files/week9.html +1723 -0
  206. data/test/hpricot/files/why.xml +19 -0
  207. data/test/hpricot/load_files.rb +11 -0
  208. data/test/hpricot/test_alter.rb +68 -0
  209. data/test/hpricot/test_builder.rb +20 -0
  210. data/test/hpricot/test_parser.rb +426 -0
  211. data/test/hpricot/test_paths.rb +15 -0
  212. data/test/hpricot/test_preserved.rb +77 -0
  213. data/test/hpricot/test_xml.rb +30 -0
  214. data/test/html/sax/test_parser.rb +52 -0
  215. data/test/html/test_builder.rb +156 -0
  216. data/test/html/test_document.rb +361 -0
  217. data/test/html/test_document_encoding.rb +46 -0
  218. data/test/html/test_document_fragment.rb +97 -0
  219. data/test/html/test_element_description.rb +95 -0
  220. data/test/html/test_named_characters.rb +14 -0
  221. data/test/html/test_node.rb +165 -0
  222. data/test/test_convert_xpath.rb +186 -0
  223. data/test/test_css_cache.rb +56 -0
  224. data/test/test_gc.rb +15 -0
  225. data/test/test_memory_leak.rb +77 -0
  226. data/test/test_nokogiri.rb +127 -0
  227. data/test/test_reader.rb +316 -0
  228. data/test/test_xslt_transforms.rb +131 -0
  229. data/test/xml/node/test_save_options.rb +20 -0
  230. data/test/xml/node/test_subclass.rb +44 -0
  231. data/test/xml/sax/test_parser.rb +169 -0
  232. data/test/xml/sax/test_push_parser.rb +92 -0
  233. data/test/xml/test_attr.rb +38 -0
  234. data/test/xml/test_builder.rb +73 -0
  235. data/test/xml/test_cdata.rb +38 -0
  236. data/test/xml/test_comment.rb +23 -0
  237. data/test/xml/test_document.rb +397 -0
  238. data/test/xml/test_document_encoding.rb +26 -0
  239. data/test/xml/test_document_fragment.rb +76 -0
  240. data/test/xml/test_dtd.rb +42 -0
  241. data/test/xml/test_dtd_encoding.rb +31 -0
  242. data/test/xml/test_entity_reference.rb +21 -0
  243. data/test/xml/test_namespace.rb +43 -0
  244. data/test/xml/test_node.rb +808 -0
  245. data/test/xml/test_node_attributes.rb +34 -0
  246. data/test/xml/test_node_encoding.rb +84 -0
  247. data/test/xml/test_node_set.rb +368 -0
  248. data/test/xml/test_parse_options.rb +52 -0
  249. data/test/xml/test_processing_instruction.rb +30 -0
  250. data/test/xml/test_reader_encoding.rb +126 -0
  251. data/test/xml/test_relax_ng.rb +60 -0
  252. data/test/xml/test_schema.rb +65 -0
  253. data/test/xml/test_text.rb +18 -0
  254. data/test/xml/test_unparented_node.rb +381 -0
  255. data/test/xml/test_xpath.rb +106 -0
  256. metadata +409 -0
@@ -0,0 +1,11 @@
1
+ module Nokogiri
2
+ module XML
3
+ class CDATA < Nokogiri::XML::Text
4
+ ###
5
+ # Get the name of this CDATA node
6
+ def name
7
+ '#cdata-section'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,100 @@
1
+ module Nokogiri
2
+ module XML
3
+ ####
4
+ # Nokogiri::XML::Document is the main entry point for dealing with
5
+ # XML documents. The Document is created by parsing an XML document.
6
+ # See Nokogiri.XML()
7
+ #
8
+ # For searching a Document, see Nokogiri::XML::Node#css and
9
+ # Nokogiri::XML::Node#xpath
10
+ class Document < Node
11
+ # A list of Nokogiri::XML::SyntaxError found when parsing a document
12
+ attr_accessor :errors
13
+
14
+ def initialize *args
15
+ @decorators = nil
16
+ end
17
+
18
+ # The name of this document. Always returns "document"
19
+ def name
20
+ 'document'
21
+ end
22
+
23
+ # A reference to +self+
24
+ def document
25
+ self
26
+ end
27
+
28
+ # Get the list of decorators given +key+
29
+ def decorators key
30
+ @decorators ||= Hash.new
31
+ @decorators[key] ||= []
32
+ end
33
+
34
+ ###
35
+ # Explore a document with shortcut methods.
36
+ def slop!
37
+ unless decorators(XML::Node).include? Nokogiri::Decorators::Slop
38
+ decorators(XML::Node) << Nokogiri::Decorators::Slop
39
+ decorate!
40
+ end
41
+
42
+ self
43
+ end
44
+
45
+ ###
46
+ # Apply any decorators to +node+
47
+ def decorate node
48
+ return unless @decorators
49
+ @decorators.each { |klass,list|
50
+ next unless node.is_a?(klass)
51
+ list.each { |moodule| node.extend(moodule) }
52
+ }
53
+ end
54
+
55
+ alias :to_xml :serialize
56
+ alias :inner_html :serialize
57
+
58
+ # Get the hash of namespaces on the root Nokogiri::XML::Node
59
+ def namespaces
60
+ root ? root.collect_namespaces : {}
61
+ end
62
+
63
+ ####
64
+ # Create a Nokogiri::XML::DocumentFragment from +tags+
65
+ def fragment tags
66
+ DocumentFragment.new(self, tags)
67
+ end
68
+
69
+ undef_method :swap, :parent, :namespace
70
+
71
+ class << self
72
+ ###
73
+ # Parse an XML file. +thing+ may be a String, or any object that
74
+ # responds to _read_ and _close_ such as an IO, or StringIO.
75
+ # +url+ is resource where this document is located. +encoding+ is the
76
+ # encoding that should be used when processing the document. +options+
77
+ # is a number that sets options in the parser, such as
78
+ # Nokogiri::XML::PARSE_RECOVER. See the constants in
79
+ # Nokogiri::XML.
80
+ def parse string_or_io, url = nil, encoding = nil, options = 2145, &block
81
+
82
+ options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
83
+ # Give the options to the user
84
+ yield options if block_given?
85
+
86
+ if string_or_io.respond_to?(:read)
87
+ url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
88
+ return self.read_io(string_or_io, url, encoding, options.to_i)
89
+ end
90
+
91
+ # read_memory pukes on empty docs
92
+ return self.new if string_or_io.nil? or string_or_io.empty?
93
+
94
+ self.read_memory(string_or_io, url, encoding, options.to_i)
95
+ end
96
+ end
97
+
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,49 @@
1
+ module Nokogiri
2
+ module XML
3
+ class DocumentFragment < Nokogiri::XML::Node
4
+ def initialize document, tags=nil
5
+ if tags
6
+ parser = if self.kind_of?(Nokogiri::HTML::DocumentFragment)
7
+ HTML::SAX::Parser.new(FragmentHandler.new(self, tags))
8
+ else
9
+ XML::SAX::Parser.new(FragmentHandler.new(self, tags))
10
+ end
11
+ parser.parse(tags)
12
+ end
13
+ end
14
+
15
+ ###
16
+ # return the name for DocumentFragment
17
+ def name
18
+ '#document-fragment'
19
+ end
20
+
21
+ def to_s
22
+ children.to_s
23
+ end
24
+
25
+ def to_html *args
26
+ children.to_html(*args)
27
+ end
28
+
29
+ def to_xhtml *args
30
+ children.to_xhtml(*args)
31
+ end
32
+
33
+ def to_xml *args
34
+ children.to_xml(*args)
35
+ end
36
+
37
+ alias :serialize :to_s
38
+
39
+ class << self
40
+ ####
41
+ # Create a Nokogiri::XML::DocumentFragment from +tags+
42
+ def parse tags
43
+ XML::DocumentFragment.new(XML::Document.new, tags)
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ module Nokogiri
2
+ module XML
3
+ class DTD < Nokogiri::XML::Node
4
+ ###
5
+ # Return attributes for DTD. Always returns +nil+
6
+ def attributes
7
+ nil
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Nokogiri
2
+ module XML
3
+ class EntityDeclaration < Nokogiri::XML::Node
4
+ ###
5
+ # return attributes. Always returns +nil+
6
+ def attributes
7
+ nil
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,55 @@
1
+ module Nokogiri
2
+ module XML
3
+ class FragmentHandler < Nokogiri::XML::SAX::Document # :nodoc:
4
+ def initialize node, original_html
5
+ @doc_started = false
6
+ @document = node.document
7
+ @stack = [node]
8
+ @klass = if node.kind_of?(Nokogiri::HTML::DocumentFragment)
9
+ Nokogiri::HTML::DocumentFragment
10
+ else
11
+ Nokogiri::XML::DocumentFragment
12
+ end
13
+ #
14
+ # the regexes used in start_element() and characters() anchor at
15
+ # start-of-line, but we really only want them to anchor at
16
+ # start-of-doc. so let's only save up to the first newline.
17
+ #
18
+ # this implementation choice was the result of some benchmarks, if
19
+ # you're curious: http://gist.github.com/115936
20
+ #
21
+ newline_index = original_html.index("\n")
22
+ @original_html = if newline_index
23
+ original_html[0,newline_index]
24
+ else
25
+ original_html
26
+ end
27
+ end
28
+
29
+ def start_element name, attrs = []
30
+ regex = (@klass == Nokogiri::HTML::DocumentFragment) ? %r{^\s*<#{Regexp.escape(name)}}i \
31
+ : %r{^\s*<#{Regexp.escape(name)}}
32
+ @doc_started = true if @original_html =~ regex
33
+ return unless @doc_started
34
+
35
+ node = Node.new(name, @document)
36
+ attrs << "" unless (attrs.length % 2) == 0
37
+ Hash[*attrs].each do |k,v|
38
+ node[k] = v
39
+ end
40
+ @stack.last << node
41
+ @stack << node
42
+ end
43
+
44
+ def characters string
45
+ @doc_started = true if @original_html.strip =~ %r{^\s*#{Regexp.escape(string.strip)}}
46
+ @stack.last << Nokogiri::XML::Text.new(string, @document)
47
+ end
48
+
49
+ def end_element name
50
+ return unless @stack.last.name == name
51
+ @stack.pop
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ module Nokogiri
2
+ module XML
3
+ class Namespace
4
+ attr_reader :document
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,745 @@
1
+ require 'stringio'
2
+ require 'nokogiri/xml/node/save_options'
3
+
4
+ module Nokogiri
5
+ module XML
6
+ ####
7
+ # Nokogiri::XML::Node is your window to the fun filled world of dealing
8
+ # with XML and HTML tags. A Nokogiri::XML::Node may be treated similarly
9
+ # to a hash with regard to attributes. For example (from irb):
10
+ #
11
+ # irb(main):004:0> node
12
+ # => <a href="#foo" id="link">link</a>
13
+ # irb(main):005:0> node['href']
14
+ # => "#foo"
15
+ # irb(main):006:0> node.keys
16
+ # => ["href", "id"]
17
+ # irb(main):007:0> node.values
18
+ # => ["#foo", "link"]
19
+ # irb(main):008:0> node['class'] = 'green'
20
+ # => "green"
21
+ # irb(main):009:0> node
22
+ # => <a href="#foo" id="link" class="green">link</a>
23
+ # irb(main):010:0>
24
+ #
25
+ # See Nokogiri::XML::Node#[] and Nokogiri::XML#[]= for more information.
26
+ #
27
+ # Nokogiri::XML::Node also has methods that let you move around your
28
+ # tree. For navigating your tree, see:
29
+ #
30
+ # * Nokogiri::XML::Node#parent
31
+ # * Nokogiri::XML::Node#children
32
+ # * Nokogiri::XML::Node#next
33
+ # * Nokogiri::XML::Node#previous
34
+ #
35
+ # You may search this node's subtree using Node#xpath and Node#css
36
+ class Node
37
+ # Element node type, see Nokogiri::XML::Node#element?
38
+ ELEMENT_NODE = 1
39
+ # Attribute node type
40
+ ATTRIBUTE_NODE = 2
41
+ # Text node type, see Nokogiri::XML::Node#text?
42
+ TEXT_NODE = 3
43
+ # CDATA node type, see Nokogiri::XML::Node#cdata?
44
+ CDATA_SECTION_NODE = 4
45
+ # Entity reference node type
46
+ ENTITY_REF_NODE = 5
47
+ # Entity node type
48
+ ENTITY_NODE = 6
49
+ # PI node type
50
+ PI_NODE = 7
51
+ # Comment node type, see Nokogiri::XML::Node#comment?
52
+ COMMENT_NODE = 8
53
+ # Document node type, see Nokogiri::XML::Node#xml?
54
+ DOCUMENT_NODE = 9
55
+ # Document type node type
56
+ DOCUMENT_TYPE_NODE = 10
57
+ # Document fragment node type
58
+ DOCUMENT_FRAG_NODE = 11
59
+ # Notation node type
60
+ NOTATION_NODE = 12
61
+ # HTML document node type, see Nokogiri::XML::Node#html?
62
+ HTML_DOCUMENT_NODE = 13
63
+ # DTD node type
64
+ DTD_NODE = 14
65
+ # Element declaration type
66
+ ELEMENT_DECL = 15
67
+ # Attribute declaration type
68
+ ATTRIBUTE_DECL = 16
69
+ # Entity declaration type
70
+ ENTITY_DECL = 17
71
+ # Namespace declaration type
72
+ NAMESPACE_DECL = 18
73
+ # XInclude start type
74
+ XINCLUDE_START = 19
75
+ # XInclude end type
76
+ XINCLUDE_END = 20
77
+ # DOCB document node type
78
+ DOCB_DOCUMENT_NODE = 21
79
+
80
+ def initialize name, document
81
+ # ... Ya. This is empty on purpose.
82
+ end
83
+
84
+ ###
85
+ # Decorate this node with the decorators set up in this node's Document
86
+ def decorate!
87
+ document.decorate(self)
88
+ end
89
+
90
+ ###
91
+ # Search this node for +paths+. +paths+ can be XPath or CSS, and an
92
+ # optional hash of namespaces may be appended.
93
+ # See Node#xpath and Node#css.
94
+ def search *paths
95
+ ns = paths.last.is_a?(Hash) ? paths.pop :
96
+ (document.root ? document.root.namespaces : {})
97
+ xpath(*(paths.map { |path|
98
+ path = path.to_s
99
+ path =~ /^(\.\/|\/)/ ? path : CSS.xpath_for(
100
+ path,
101
+ :prefix => ".//",
102
+ :ns => ns
103
+ )
104
+ }.flatten.uniq) + [ns])
105
+ end
106
+ alias :/ :search
107
+
108
+ ###
109
+ # Search this node for XPath +paths+. +paths+ must be one or more XPath
110
+ # queries. A hash of namespaces may be appended. For example:
111
+ #
112
+ # node.xpath('.//title')
113
+ # node.xpath('.//foo:name', { 'foo' => 'http://example.org/' })
114
+ # node.xpath('.//xmlns:name', node.root.namespaces)
115
+ #
116
+ # Custom XPath functions may also be defined. To define custom functions
117
+ # create a class and implement the # function you want to define.
118
+ # For example:
119
+ #
120
+ # node.xpath('.//title[regex(., "\w+")]', Class.new {
121
+ # def regex node_set, regex
122
+ # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
123
+ # end
124
+ # }.new)
125
+ #
126
+ def xpath *paths
127
+ # Pop off our custom function handler if it exists
128
+ handler = ![
129
+ Hash, String, Symbol
130
+ ].include?(paths.last.class) ? paths.pop : nil
131
+
132
+ ns = paths.last.is_a?(Hash) ? paths.pop :
133
+ (document.root ? document.root.namespaces : {})
134
+
135
+ return NodeSet.new(document) unless document
136
+
137
+ sets = paths.map { |path|
138
+ ctx = XPathContext.new(self)
139
+ ctx.register_namespaces(ns)
140
+ set = ctx.evaluate(path, handler).node_set
141
+ set.document = document
142
+ document.decorate(set)
143
+ set
144
+ }
145
+ return sets.first if sets.length == 1
146
+
147
+ NodeSet.new(document) do |combined|
148
+ document.decorate(combined)
149
+ sets.each do |set|
150
+ set.each do |node|
151
+ combined << node
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ ###
158
+ # Search this node for CSS +rules+. +rules+ must be one or more CSS
159
+ # selectors. For example:
160
+ #
161
+ # node.css('title')
162
+ # node.css('body h1.bold')
163
+ # node.css('div + p.green', 'div#one')
164
+ #
165
+ # Custom CSS pseudo classes may also be defined. To define custom pseudo
166
+ # classes, create a class and implement the custom pseudo class you
167
+ # want defined. The first argument to the method will be the current
168
+ # matching NodeSet. Any other arguments are ones that you pass in.
169
+ # For example:
170
+ #
171
+ # node.css('title:regex("\w+")', Class.new {
172
+ # def regex node_set, regex
173
+ # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
174
+ # end
175
+ # }.new)
176
+ #
177
+ def css *rules
178
+ # Pop off our custom function handler if it exists
179
+ handler = ![
180
+ Hash, String, Symbol
181
+ ].include?(rules.last.class) ? rules.pop : nil
182
+
183
+ ns = rules.last.is_a?(Hash) ? rules.pop :
184
+ (document.root ? document.root.namespaces : {})
185
+
186
+ rules = rules.map { |rule|
187
+ CSS.xpath_for(rule, :prefix => ".//", :ns => ns)
188
+ }.flatten.uniq + [ns, handler].compact
189
+
190
+ xpath(*rules)
191
+ end
192
+
193
+ ###
194
+ # Search for the first occurrence of +path+.
195
+ # Returns nil if nothing is found, otherwise a Node.
196
+ def at path, ns = document.root ? document.root.namespaces : {}
197
+ search(path, ns).first
198
+ end
199
+ alias :% :at
200
+
201
+ ###
202
+ # Get the attribute value for the attribute +name+
203
+ def [] name
204
+ return nil unless key?(name.to_s)
205
+ get(name.to_s)
206
+ end
207
+
208
+ alias :next :next_sibling
209
+ alias :previous :previous_sibling
210
+ alias :remove :unlink
211
+ alias :get_attribute :[]
212
+ alias :set_attribute :[]=
213
+ alias :text :content
214
+ alias :inner_text :content
215
+ alias :has_attribute? :key?
216
+ alias :<< :add_child
217
+ alias :name :node_name
218
+ alias :name= :node_name=
219
+ alias :type :node_type
220
+ alias :to_str :text
221
+ alias :clone :dup
222
+
223
+ ####
224
+ # Returns a hash containing the node's attributes. The key is the
225
+ # attribute name, the value is the string value of the attribute.
226
+ def attributes
227
+ Hash[*(attribute_nodes.map { |node|
228
+ [node.node_name, node]
229
+ }.flatten)]
230
+ end
231
+
232
+ ###
233
+ # Get the attribute values for this Node.
234
+ def values
235
+ attribute_nodes.map { |node| node.value }
236
+ end
237
+
238
+ ###
239
+ # Get the attribute names for this Node.
240
+ def keys
241
+ attribute_nodes.map { |node| node.node_name }
242
+ end
243
+
244
+ ###
245
+ # Iterate over each attribute name and value pair for this Node.
246
+ def each &block
247
+ attribute_nodes.each { |node|
248
+ block.call(node.node_name, node.value)
249
+ }
250
+ end
251
+
252
+ ###
253
+ # Remove the attribute named +name+
254
+ def remove_attribute name
255
+ attributes[name].remove if key? name
256
+ end
257
+ alias :delete :remove_attribute
258
+
259
+ ###
260
+ # Returns true if this Node matches +selector+
261
+ def matches? selector
262
+ document.search(selector).include?(self)
263
+ end
264
+
265
+ ####
266
+ # Create nodes from +data+ and insert them before this node
267
+ # (as a sibling).
268
+ def before data
269
+ fragment(data).children.each do |node|
270
+ add_previous_sibling node
271
+ end
272
+ self
273
+ end
274
+
275
+ ####
276
+ # Create nodes from +data+ and insert them after this node
277
+ # (as a sibling).
278
+ def after data
279
+ fragment(data).children.to_a.reverse.each do |node|
280
+ add_next_sibling node
281
+ end
282
+ self
283
+ end
284
+
285
+ ####
286
+ # Swap this Node for new nodes made from +data+
287
+ def swap data
288
+ before(data)
289
+ remove
290
+ self
291
+ end
292
+
293
+ ####
294
+ # Set the inner_html for this Node to +tags+
295
+ def inner_html= tags
296
+ children.each { |x| x.remove}
297
+
298
+ fragment(tags).children.to_a.reverse.each do |node|
299
+ add_child node
300
+ end
301
+ self
302
+ end
303
+
304
+ def fragment tags # :nodoc:
305
+ # TODO: deprecate?
306
+ document.fragment(tags)
307
+ end
308
+
309
+ ####
310
+ # Set the Node content to +string+. The content gets XML escaped.
311
+ def content= string
312
+ self.native_content = encode_special_chars(string.to_s)
313
+ end
314
+
315
+ ###
316
+ # Set the parent Node for this Node
317
+ def parent= parent_node
318
+ parent_node.add_child(self)
319
+ parent_node
320
+ end
321
+
322
+ ###
323
+ # Get a hash containing the Namespace definitions for this Node
324
+ def namespaces
325
+ Hash[*namespace_definitions.map { |nd|
326
+ key = ['xmlns', nd.prefix].compact.join(':')
327
+ if defined?(Encoding) && document.encoding
328
+ begin
329
+ key.force_encoding document.encoding
330
+ rescue ArgumentError
331
+ end
332
+ end
333
+ [key, nd.href]
334
+ }.flatten]
335
+ end
336
+
337
+ # Returns true if this is a Comment
338
+ def comment?
339
+ type == COMMENT_NODE
340
+ end
341
+
342
+ # Returns true if this is a CDATA
343
+ def cdata?
344
+ type == CDATA_SECTION_NODE
345
+ end
346
+
347
+ # Returns true if this is an XML::Document node
348
+ def xml?
349
+ type == DOCUMENT_NODE
350
+ end
351
+
352
+ # Returns true if this is an HTML::Document node
353
+ def html?
354
+ type == HTML_DOCUMENT_NODE
355
+ end
356
+
357
+ # Returns true if this is a Text node
358
+ def text?
359
+ type == TEXT_NODE
360
+ end
361
+
362
+ ###
363
+ # Fetch the Nokogiri::HTML::ElementDescription for this node. Returns
364
+ # nil on XML documents and on unknown tags.
365
+ def description
366
+ return nil if document.xml?
367
+ Nokogiri::HTML::ElementDescription[name]
368
+ end
369
+
370
+ ###
371
+ # Is this a read only node?
372
+ def read_only?
373
+ # According to gdome2, these are read-only node types
374
+ [NOTATION_NODE, ENTITY_NODE, ENTITY_DECL].include?(type)
375
+ end
376
+
377
+ # Returns true if this is an Element node
378
+ def element?
379
+ type == ELEMENT_NODE
380
+ end
381
+ alias :elem? :element?
382
+
383
+ ###
384
+ # Turn this node in to a string. If the document is HTML, this method
385
+ # returns html. If the document is XML, this method returns XML.
386
+ def to_s
387
+ document.xml? ? to_xml : to_html
388
+ end
389
+
390
+ # Get the inner_html for this node's Node#children
391
+ def inner_html
392
+ children.map { |x| x.to_html }.join
393
+ end
394
+
395
+ # Get the path to this node as a CSS expression
396
+ def css_path
397
+ path.split(/\//).map { |part|
398
+ part.length == 0 ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
399
+ }.compact.join(' > ')
400
+ end
401
+
402
+ # recursively get all namespaces from this node and its subtree
403
+ def collect_namespaces
404
+ # TODO: print warning message if a prefix refers to more than one URI in the document?
405
+ ns = {}
406
+ traverse {|j| ns.merge!(j.namespaces)}
407
+ ns
408
+ end
409
+
410
+ ###
411
+ # Get a list of ancestor Node for this Node. If +selector+ is given,
412
+ # the ancestors must match +selector+
413
+ def ancestors selector = nil
414
+ return NodeSet.new(document) unless respond_to?(:parent)
415
+ return NodeSet.new(document) unless parent
416
+
417
+ parents = [parent]
418
+
419
+ while parents.last.respond_to?(:parent)
420
+ break unless ctx_parent = parents.last.parent
421
+ parents << ctx_parent
422
+ end
423
+
424
+ return NodeSet.new(document, parents) unless selector
425
+
426
+ NodeSet.new(document, parents.find_all { |parent|
427
+ parent.matches?(selector)
428
+ })
429
+ end
430
+
431
+ ###
432
+ # Set the default namespace for this node to +url+
433
+ def default_namespace= url
434
+ add_namespace_definition(nil, url)
435
+ end
436
+ alias :add_namespace :add_namespace_definition
437
+
438
+ ###
439
+ # Set the namespace for this node to +ns+
440
+ def namespace= ns
441
+ if ns.document != document
442
+ raise ArgumentError, 'namespace must be declared on the same document'
443
+ end
444
+ unless ns.is_a? Nokogiri::XML::Namespace
445
+ raise TypeError, "#{ns.class} can't be coerced into Nokogiri::XML::Namespace"
446
+ end
447
+ set_namespace ns
448
+ end
449
+
450
+ ####
451
+ # Yields self and all children to +block+ recursively.
452
+ def traverse &block
453
+ children.each{|j| j.traverse(&block) }
454
+ block.call(self)
455
+ end
456
+
457
+ ###
458
+ # Accept a visitor. This method calls "visit" on +visitor+ with self.
459
+ def accept visitor
460
+ visitor.visit(self)
461
+ end
462
+
463
+ ####
464
+ # replace this Node with the +new_node+ in the Document.
465
+ def replace(new_node)
466
+ if new_node.is_a?(Document) || !new_node.is_a?(XML::Node)
467
+ raise ArgumentError, <<-EOERR
468
+ Node.replace requires a Node argument, and cannot accept a Document.
469
+ (You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
470
+ EOERR
471
+ end
472
+ replace_with_node new_node
473
+ end
474
+
475
+ ###
476
+ # Test to see if this Node is equal to +other+
477
+ def == other
478
+ return false unless other
479
+ return false unless other.respond_to?(:pointer_id)
480
+ pointer_id == other.pointer_id
481
+ end
482
+
483
+ ###
484
+ # Serialize Node using +options+. Save options
485
+ # can also be set using a block. See SaveOptions.
486
+ #
487
+ # These two statements are equivalent:
488
+ #
489
+ # node.serialize(:encoding => 'UTF-8', :save_with => FORMAT | AS_XML)
490
+ #
491
+ # or
492
+ #
493
+ # node.serialize(:encoding => 'UTF-8') do |config|
494
+ # config.format.as_xml
495
+ # end
496
+ #
497
+ def serialize *args, &block
498
+ if args.first && !args.first.is_a?(Hash)
499
+ $stderr.puts(<<-eowarn)
500
+ #{self.class}#serialize(encoding, save_opts) is deprecated and will be removed in
501
+ Nokogiri version 1.4.0 *or* after June 1 2009.
502
+ You called serialize from here:
503
+
504
+ #{caller.first}
505
+
506
+ Please change to #{self.class}#serialize(:encoding => enc, :save_with => opts)
507
+ eowarn
508
+ end
509
+
510
+ options = args.first.is_a?(Hash) ? args.shift : {
511
+ :encoding => args[0],
512
+ :save_with => args[1] || SaveOptions::FORMAT
513
+ }
514
+
515
+ io = StringIO.new
516
+ write_to io, options, &block
517
+ io.rewind
518
+ io.read
519
+ end
520
+
521
+ ###
522
+ # Serialize this Node to HTML
523
+ #
524
+ # doc.to_html
525
+ #
526
+ # See Node#write_to for a list of +options+. For formatted output,
527
+ # use Node#to_xhtml instead.
528
+ def to_html options = {}
529
+ if options.is_a?(String)
530
+ $stderr.puts(<<-eowarn)
531
+ Node#to_html(encoding) is deprecated and will be removed in
532
+ Nokogiri version 1.4.0 *or* after June 1 2009.
533
+ You called to_html from here:
534
+
535
+ #{caller.first}
536
+
537
+ Please change to Node#to_html(:encoding => #{options})
538
+ eowarn
539
+ options = { :encoding => options }
540
+ end
541
+
542
+ # FIXME: this is a hack around broken libxml versions
543
+ return dump_html if %w[2 6] === LIBXML_VERSION.split('.')[0..1]
544
+
545
+ options[:save_with] ||= SaveOptions::FORMAT |
546
+ SaveOptions::NO_DECLARATION |
547
+ SaveOptions::NO_EMPTY_TAGS |
548
+ SaveOptions::AS_HTML
549
+
550
+ serialize(options)
551
+ end
552
+
553
+ ###
554
+ # Serialize this Node to XML using +options+
555
+ #
556
+ # doc.to_xml(:indent => 5, :encoding => 'UTF-8')
557
+ #
558
+ # See Node#write_to for a list of +options+
559
+ def to_xml options = {}
560
+ encoding = nil
561
+
562
+ # FIXME add a deprecation warning
563
+ if options.is_a? String
564
+ $stderr.puts(<<-eowarn)
565
+ Node#to_xml(encoding) is deprecated and will be removed in
566
+ Nokogiri version 1.4.0 *or* after June 1 2009.
567
+ You called to_xml from here:
568
+
569
+ #{caller.first}
570
+
571
+ Please change to Node#to_xml(:encoding => #{options})
572
+ eowarn
573
+ options = {
574
+ :encoding => options
575
+ }
576
+ end
577
+ options[:save_with] ||= SaveOptions::FORMAT | SaveOptions::AS_XML
578
+
579
+ serialize(options)
580
+ end
581
+
582
+ ###
583
+ # Serialize this Node to XHTML using +options+
584
+ #
585
+ # doc.to_xhtml(:indent => 5, :encoding => 'UTF-8')
586
+ #
587
+ # See Node#write_to for a list of +options+
588
+ def to_xhtml options = {}
589
+ if options.is_a?(String)
590
+ options = { :encoding => options }
591
+ $stderr.puts(<<-eowarn)
592
+ Node#to_xml(encoding) is deprecated and will be removed in
593
+ Nokogiri version 1.4.0 *or* after June 1 2009.
594
+ You called to_xhtml from here:
595
+
596
+ #{caller.first}
597
+
598
+ Please change to Node#to_xhtml(:encoding => #{options})
599
+ eowarn
600
+ end
601
+
602
+ # FIXME: this is a hack around broken libxml versions
603
+ return dump_html if %w[2 6] === LIBXML_VERSION.split('.')[0..1]
604
+
605
+ options[:save_with] ||= SaveOptions::FORMAT |
606
+ SaveOptions::NO_DECLARATION |
607
+ SaveOptions::NO_EMPTY_TAGS |
608
+ SaveOptions::AS_XHTML
609
+
610
+ serialize(options)
611
+ end
612
+
613
+ ###
614
+ # Write Node to +io+ with +options+. +options+ modify the output of
615
+ # this method. Valid options are:
616
+ #
617
+ # * +:encoding+ for changing the encoding
618
+ # * +:indent_text+ the indentation text, defaults to one space
619
+ # * +:indent+ the number of +:indent_text+ to use, defaults to 2
620
+ # * +:save_with+ a combination of SaveOptions constants.
621
+ #
622
+ # To save with UTF-8 indented twice:
623
+ #
624
+ # node.write_to(io, :encoding => 'UTF-8', :indent => 2)
625
+ #
626
+ # To save indented with two dashes:
627
+ #
628
+ # node.write_to(io, :indent_text => '-', :indent => 2
629
+ #
630
+ def write_to io, *options
631
+ if options.length > 0 && !options.first.is_a?(Hash)
632
+ $stderr.puts(<<-eowarn)
633
+ Node#write_to(io, encoding, save_options) is deprecated and will be removed in
634
+ Nokogiri version 1.4.0 *or* after June 1 2009.
635
+ You called write_to from here:
636
+
637
+ #{caller.first}
638
+
639
+ Please change to: Node#write_to(io, :encoding => e, :save_options => opts)
640
+ eowarn
641
+ end
642
+
643
+ options = options.first.is_a?(Hash) ? options.shift : {}
644
+ encoding = options[:encoding] || options[0]
645
+ save_options = options[:save_with] || options[1] || SaveOptions::FORMAT
646
+ indent_text = options[:indent_text] || ' '
647
+ indent_times = options[:indent] || 2
648
+
649
+
650
+ config = SaveOptions.new(save_options)
651
+ yield config if block_given?
652
+
653
+ native_write_to(io, encoding, indent_text * indent_times, config.options)
654
+ end
655
+
656
+ ###
657
+ # Write Node as HTML to +io+ with +options+
658
+ #
659
+ # See Node#write_to for a list of +options+
660
+ def write_html_to io, options = {}
661
+ if options.is_a?(String)
662
+ $stderr.puts(<<-eowarn)
663
+ Node#write_html_to(io, encoding) is deprecated and will be removed in
664
+ Nokogiri version 1.4.0 *or* after June 1 2009.
665
+ You called write_html_to from here:
666
+
667
+ #{caller.first}
668
+
669
+ Please change to Node#write_html_to(io, :encoding => #{options})
670
+ eowarn
671
+ options = { :encoding => options }
672
+ end
673
+
674
+ # FIXME: this is a hack around broken libxml versions
675
+ return (io << dump_html) if %w[2 6] === LIBXML_VERSION.split('.')[0..1]
676
+
677
+ options[:save_with] ||= SaveOptions::FORMAT |
678
+ SaveOptions::NO_DECLARATION |
679
+ SaveOptions::NO_EMPTY_TAGS |
680
+ SaveOptions::AS_HTML
681
+ write_to io, options
682
+ end
683
+
684
+ ###
685
+ # Write Node as XHTML to +io+ with +options+
686
+ #
687
+ # See Node#write_to for a list of +options+
688
+ def write_xhtml_to io, options = {}
689
+ if options.is_a?(String)
690
+ $stderr.puts(<<-eowarn)
691
+ Node#write_xhtml_to(io, encoding) is deprecated and will be removed in
692
+ Nokogiri version 1.4.0 *or* after June 1 2009.
693
+ You called write_xhtml_to from here:
694
+
695
+ #{caller.first}
696
+
697
+ Please change to Node#write_xhtml_to(io, :encoding => #{options})
698
+ eowarn
699
+ options = { :encoding => options }
700
+ end
701
+
702
+ # FIXME: this is a hack around broken libxml versions
703
+ return (io << dump_html) if %w[2 6] === LIBXML_VERSION.split('.')[0..1]
704
+
705
+ options[:save_with] ||= SaveOptions::FORMAT |
706
+ SaveOptions::NO_DECLARATION |
707
+ SaveOptions::NO_EMPTY_TAGS |
708
+ SaveOptions::AS_XHTML
709
+ write_to io, options
710
+ end
711
+
712
+ ###
713
+ # Write Node as XML to +io+ with +options+
714
+ #
715
+ # doc.write_xml_to io, :encoding => 'UTF-8'
716
+ #
717
+ # See Node#write_to for a list of options
718
+ def write_xml_to io, options = {}
719
+ if options.is_a?(String)
720
+ $stderr.puts(<<-eowarn)
721
+ Node#write_xml_to(io, encoding) is deprecated and will be removed in
722
+ Nokogiri version 1.4.0 *or* after June 1 2009.
723
+ You called write_xml_to from here:
724
+
725
+ #{caller.first}
726
+
727
+ Please change to Node#write_xml_to(io, :encoding => #{options})
728
+ eowarn
729
+ options = { :encoding => options }
730
+ end
731
+ options[:save_with] ||= SaveOptions::FORMAT | SaveOptions::AS_XML
732
+ write_to io, options
733
+ end
734
+
735
+ ###
736
+ # Compare two Node objects with respect to their Document. Nodes from
737
+ # different documents cannot be compared.
738
+ def <=> other
739
+ return nil unless other.is_a?(Nokogiri::XML::Node)
740
+ return nil unless document == other.document
741
+ compare other
742
+ end
743
+ end
744
+ end
745
+ end