nokogiri-fitzsimmons 1.5.5.3-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (297) hide show
  1. data/.autotest +26 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.ja.rdoc +666 -0
  4. data/CHANGELOG.rdoc +659 -0
  5. data/C_CODING_STYLE.rdoc +33 -0
  6. data/Manifest.txt +295 -0
  7. data/README.ja.rdoc +106 -0
  8. data/README.rdoc +178 -0
  9. data/ROADMAP.md +86 -0
  10. data/Rakefile +194 -0
  11. data/STANDARD_RESPONSES.md +47 -0
  12. data/Y_U_NO_GEMSPEC.md +155 -0
  13. data/bin/nokogiri +63 -0
  14. data/build_all +58 -0
  15. data/ext/java/nokogiri/EncodingHandler.java +124 -0
  16. data/ext/java/nokogiri/HtmlDocument.java +163 -0
  17. data/ext/java/nokogiri/HtmlElementDescription.java +145 -0
  18. data/ext/java/nokogiri/HtmlEntityLookup.java +79 -0
  19. data/ext/java/nokogiri/HtmlSaxParserContext.java +259 -0
  20. data/ext/java/nokogiri/NokogiriService.java +598 -0
  21. data/ext/java/nokogiri/XmlAttr.java +190 -0
  22. data/ext/java/nokogiri/XmlAttributeDecl.java +130 -0
  23. data/ext/java/nokogiri/XmlCdata.java +84 -0
  24. data/ext/java/nokogiri/XmlComment.java +95 -0
  25. data/ext/java/nokogiri/XmlDocument.java +580 -0
  26. data/ext/java/nokogiri/XmlDocumentFragment.java +234 -0
  27. data/ext/java/nokogiri/XmlDtd.java +469 -0
  28. data/ext/java/nokogiri/XmlElement.java +97 -0
  29. data/ext/java/nokogiri/XmlElementContent.java +382 -0
  30. data/ext/java/nokogiri/XmlElementDecl.java +152 -0
  31. data/ext/java/nokogiri/XmlEntityDecl.java +162 -0
  32. data/ext/java/nokogiri/XmlEntityReference.java +97 -0
  33. data/ext/java/nokogiri/XmlNamespace.java +215 -0
  34. data/ext/java/nokogiri/XmlNode.java +1534 -0
  35. data/ext/java/nokogiri/XmlNodeSet.java +270 -0
  36. data/ext/java/nokogiri/XmlProcessingInstruction.java +99 -0
  37. data/ext/java/nokogiri/XmlReader.java +456 -0
  38. data/ext/java/nokogiri/XmlRelaxng.java +144 -0
  39. data/ext/java/nokogiri/XmlSaxParserContext.java +356 -0
  40. data/ext/java/nokogiri/XmlSaxPushParser.java +215 -0
  41. data/ext/java/nokogiri/XmlSchema.java +324 -0
  42. data/ext/java/nokogiri/XmlSyntaxError.java +136 -0
  43. data/ext/java/nokogiri/XmlText.java +119 -0
  44. data/ext/java/nokogiri/XmlXpathContext.java +203 -0
  45. data/ext/java/nokogiri/XsltStylesheet.java +360 -0
  46. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +243 -0
  47. data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +73 -0
  48. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +86 -0
  49. data/ext/java/nokogiri/internals/NokogiriHandler.java +333 -0
  50. data/ext/java/nokogiri/internals/NokogiriHelpers.java +800 -0
  51. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +163 -0
  52. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +130 -0
  53. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +74 -0
  54. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +121 -0
  55. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +79 -0
  56. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +141 -0
  57. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +73 -0
  58. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +67 -0
  59. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +87 -0
  60. data/ext/java/nokogiri/internals/ParserContext.java +288 -0
  61. data/ext/java/nokogiri/internals/ReaderNode.java +531 -0
  62. data/ext/java/nokogiri/internals/SaveContextVisitor.java +775 -0
  63. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +76 -0
  64. data/ext/java/nokogiri/internals/XmlDeclHandler.java +42 -0
  65. data/ext/java/nokogiri/internals/XmlDomParser.java +105 -0
  66. data/ext/java/nokogiri/internals/XmlDomParserContext.java +266 -0
  67. data/ext/java/nokogiri/internals/XmlSaxParser.java +65 -0
  68. data/ext/java/nokogiri/internals/XsltExtensionFunction.java +72 -0
  69. data/ext/nokogiri/depend +358 -0
  70. data/ext/nokogiri/extconf.rb +142 -0
  71. data/ext/nokogiri/html_document.c +170 -0
  72. data/ext/nokogiri/html_document.h +10 -0
  73. data/ext/nokogiri/html_element_description.c +276 -0
  74. data/ext/nokogiri/html_element_description.h +10 -0
  75. data/ext/nokogiri/html_entity_lookup.c +32 -0
  76. data/ext/nokogiri/html_entity_lookup.h +8 -0
  77. data/ext/nokogiri/html_sax_parser_context.c +116 -0
  78. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  79. data/ext/nokogiri/html_sax_push_parser.c +87 -0
  80. data/ext/nokogiri/html_sax_push_parser.h +9 -0
  81. data/ext/nokogiri/nokogiri.c +133 -0
  82. data/ext/nokogiri/nokogiri.h +160 -0
  83. data/ext/nokogiri/xml_attr.c +94 -0
  84. data/ext/nokogiri/xml_attr.h +9 -0
  85. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  86. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  87. data/ext/nokogiri/xml_cdata.c +56 -0
  88. data/ext/nokogiri/xml_cdata.h +9 -0
  89. data/ext/nokogiri/xml_comment.c +54 -0
  90. data/ext/nokogiri/xml_comment.h +9 -0
  91. data/ext/nokogiri/xml_document.c +576 -0
  92. data/ext/nokogiri/xml_document.h +23 -0
  93. data/ext/nokogiri/xml_document_fragment.c +48 -0
  94. data/ext/nokogiri/xml_document_fragment.h +10 -0
  95. data/ext/nokogiri/xml_dtd.c +202 -0
  96. data/ext/nokogiri/xml_dtd.h +10 -0
  97. data/ext/nokogiri/xml_element_content.c +123 -0
  98. data/ext/nokogiri/xml_element_content.h +10 -0
  99. data/ext/nokogiri/xml_element_decl.c +69 -0
  100. data/ext/nokogiri/xml_element_decl.h +9 -0
  101. data/ext/nokogiri/xml_encoding_handler.c +79 -0
  102. data/ext/nokogiri/xml_encoding_handler.h +8 -0
  103. data/ext/nokogiri/xml_entity_decl.c +110 -0
  104. data/ext/nokogiri/xml_entity_decl.h +10 -0
  105. data/ext/nokogiri/xml_entity_reference.c +52 -0
  106. data/ext/nokogiri/xml_entity_reference.h +9 -0
  107. data/ext/nokogiri/xml_io.c +56 -0
  108. data/ext/nokogiri/xml_io.h +11 -0
  109. data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
  110. data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
  111. data/ext/nokogiri/xml_namespace.c +78 -0
  112. data/ext/nokogiri/xml_namespace.h +13 -0
  113. data/ext/nokogiri/xml_node.c +1480 -0
  114. data/ext/nokogiri/xml_node.h +13 -0
  115. data/ext/nokogiri/xml_node_set.c +467 -0
  116. data/ext/nokogiri/xml_node_set.h +14 -0
  117. data/ext/nokogiri/xml_processing_instruction.c +56 -0
  118. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  119. data/ext/nokogiri/xml_reader.c +684 -0
  120. data/ext/nokogiri/xml_reader.h +10 -0
  121. data/ext/nokogiri/xml_relax_ng.c +161 -0
  122. data/ext/nokogiri/xml_relax_ng.h +9 -0
  123. data/ext/nokogiri/xml_sax_parser.c +293 -0
  124. data/ext/nokogiri/xml_sax_parser.h +39 -0
  125. data/ext/nokogiri/xml_sax_parser_context.c +222 -0
  126. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  127. data/ext/nokogiri/xml_sax_push_parser.c +115 -0
  128. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  129. data/ext/nokogiri/xml_schema.c +205 -0
  130. data/ext/nokogiri/xml_schema.h +9 -0
  131. data/ext/nokogiri/xml_syntax_error.c +58 -0
  132. data/ext/nokogiri/xml_syntax_error.h +13 -0
  133. data/ext/nokogiri/xml_text.c +52 -0
  134. data/ext/nokogiri/xml_text.h +9 -0
  135. data/ext/nokogiri/xml_xpath_context.c +319 -0
  136. data/ext/nokogiri/xml_xpath_context.h +10 -0
  137. data/ext/nokogiri/xslt_stylesheet.c +270 -0
  138. data/ext/nokogiri/xslt_stylesheet.h +14 -0
  139. data/lib/isorelax.jar +0 -0
  140. data/lib/jing.jar +0 -0
  141. data/lib/nekodtd.jar +0 -0
  142. data/lib/nekohtml.jar +0 -0
  143. data/lib/nokogiri.rb +127 -0
  144. data/lib/nokogiri/css.rb +27 -0
  145. data/lib/nokogiri/css/node.rb +102 -0
  146. data/lib/nokogiri/css/parser.rb +720 -0
  147. data/lib/nokogiri/css/parser.y +258 -0
  148. data/lib/nokogiri/css/parser_extras.rb +91 -0
  149. data/lib/nokogiri/css/syntax_error.rb +7 -0
  150. data/lib/nokogiri/css/tokenizer.rb +152 -0
  151. data/lib/nokogiri/css/tokenizer.rex +55 -0
  152. data/lib/nokogiri/css/xpath_visitor.rb +171 -0
  153. data/lib/nokogiri/decorators/slop.rb +35 -0
  154. data/lib/nokogiri/html.rb +37 -0
  155. data/lib/nokogiri/html/builder.rb +35 -0
  156. data/lib/nokogiri/html/document.rb +254 -0
  157. data/lib/nokogiri/html/document_fragment.rb +41 -0
  158. data/lib/nokogiri/html/element_description.rb +23 -0
  159. data/lib/nokogiri/html/element_description_defaults.rb +671 -0
  160. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  161. data/lib/nokogiri/html/sax/parser.rb +52 -0
  162. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  163. data/lib/nokogiri/html/sax/push_parser.rb +16 -0
  164. data/lib/nokogiri/nokogiri.jar +0 -0
  165. data/lib/nokogiri/syntax_error.rb +4 -0
  166. data/lib/nokogiri/version.rb +88 -0
  167. data/lib/nokogiri/xml.rb +73 -0
  168. data/lib/nokogiri/xml/attr.rb +14 -0
  169. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  170. data/lib/nokogiri/xml/builder.rb +431 -0
  171. data/lib/nokogiri/xml/cdata.rb +11 -0
  172. data/lib/nokogiri/xml/character_data.rb +7 -0
  173. data/lib/nokogiri/xml/document.rb +267 -0
  174. data/lib/nokogiri/xml/document_fragment.rb +103 -0
  175. data/lib/nokogiri/xml/dtd.rb +22 -0
  176. data/lib/nokogiri/xml/element_content.rb +36 -0
  177. data/lib/nokogiri/xml/element_decl.rb +13 -0
  178. data/lib/nokogiri/xml/entity_decl.rb +19 -0
  179. data/lib/nokogiri/xml/namespace.rb +13 -0
  180. data/lib/nokogiri/xml/node.rb +946 -0
  181. data/lib/nokogiri/xml/node/save_options.rb +61 -0
  182. data/lib/nokogiri/xml/node_set.rb +357 -0
  183. data/lib/nokogiri/xml/notation.rb +6 -0
  184. data/lib/nokogiri/xml/parse_options.rb +98 -0
  185. data/lib/nokogiri/xml/pp.rb +2 -0
  186. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  187. data/lib/nokogiri/xml/pp/node.rb +56 -0
  188. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  189. data/lib/nokogiri/xml/reader.rb +112 -0
  190. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  191. data/lib/nokogiri/xml/sax.rb +4 -0
  192. data/lib/nokogiri/xml/sax/document.rb +164 -0
  193. data/lib/nokogiri/xml/sax/parser.rb +115 -0
  194. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  195. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  196. data/lib/nokogiri/xml/schema.rb +63 -0
  197. data/lib/nokogiri/xml/syntax_error.rb +47 -0
  198. data/lib/nokogiri/xml/text.rb +9 -0
  199. data/lib/nokogiri/xml/xpath.rb +10 -0
  200. data/lib/nokogiri/xml/xpath/syntax_error.rb +11 -0
  201. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  202. data/lib/nokogiri/xslt.rb +56 -0
  203. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  204. data/lib/xercesImpl.jar +0 -0
  205. data/lib/xsd/xmlparser/nokogiri.rb +90 -0
  206. data/tasks/cross_compile.rb +153 -0
  207. data/tasks/nokogiri.org.rb +24 -0
  208. data/tasks/test.rb +95 -0
  209. data/test/css/test_nthiness.rb +159 -0
  210. data/test/css/test_parser.rb +341 -0
  211. data/test/css/test_tokenizer.rb +198 -0
  212. data/test/css/test_xpath_visitor.rb +91 -0
  213. data/test/decorators/test_slop.rb +16 -0
  214. data/test/files/2ch.html +108 -0
  215. data/test/files/address_book.rlx +12 -0
  216. data/test/files/address_book.xml +10 -0
  217. data/test/files/bar/bar.xsd +4 -0
  218. data/test/files/dont_hurt_em_why.xml +422 -0
  219. data/test/files/encoding.html +82 -0
  220. data/test/files/encoding.xhtml +84 -0
  221. data/test/files/exslt.xml +8 -0
  222. data/test/files/exslt.xslt +35 -0
  223. data/test/files/foo/foo.xsd +4 -0
  224. data/test/files/metacharset.html +10 -0
  225. data/test/files/noencoding.html +47 -0
  226. data/test/files/po.xml +32 -0
  227. data/test/files/po.xsd +66 -0
  228. data/test/files/shift_jis.html +10 -0
  229. data/test/files/shift_jis.xml +5 -0
  230. data/test/files/snuggles.xml +3 -0
  231. data/test/files/staff.dtd +10 -0
  232. data/test/files/staff.xml +59 -0
  233. data/test/files/staff.xslt +32 -0
  234. data/test/files/tlm.html +850 -0
  235. data/test/files/to_be_xincluded.xml +2 -0
  236. data/test/files/valid_bar.xml +2 -0
  237. data/test/files/xinclude.xml +4 -0
  238. data/test/helper.rb +147 -0
  239. data/test/html/sax/test_parser.rb +138 -0
  240. data/test/html/sax/test_parser_context.rb +46 -0
  241. data/test/html/test_builder.rb +164 -0
  242. data/test/html/test_document.rb +529 -0
  243. data/test/html/test_document_encoding.rb +138 -0
  244. data/test/html/test_document_fragment.rb +254 -0
  245. data/test/html/test_element_description.rb +100 -0
  246. data/test/html/test_named_characters.rb +14 -0
  247. data/test/html/test_node.rb +188 -0
  248. data/test/html/test_node_encoding.rb +27 -0
  249. data/test/test_convert_xpath.rb +135 -0
  250. data/test/test_css_cache.rb +45 -0
  251. data/test/test_encoding_handler.rb +46 -0
  252. data/test/test_memory_leak.rb +152 -0
  253. data/test/test_nokogiri.rb +132 -0
  254. data/test/test_reader.rb +488 -0
  255. data/test/test_soap4r_sax.rb +52 -0
  256. data/test/test_xslt_transforms.rb +254 -0
  257. data/test/xml/node/test_save_options.rb +28 -0
  258. data/test/xml/node/test_subclass.rb +44 -0
  259. data/test/xml/sax/test_parser.rb +338 -0
  260. data/test/xml/sax/test_parser_context.rb +106 -0
  261. data/test/xml/sax/test_push_parser.rb +157 -0
  262. data/test/xml/test_attr.rb +64 -0
  263. data/test/xml/test_attribute_decl.rb +86 -0
  264. data/test/xml/test_builder.rb +248 -0
  265. data/test/xml/test_c14n.rb +151 -0
  266. data/test/xml/test_cdata.rb +48 -0
  267. data/test/xml/test_comment.rb +29 -0
  268. data/test/xml/test_document.rb +742 -0
  269. data/test/xml/test_document_encoding.rb +28 -0
  270. data/test/xml/test_document_fragment.rb +216 -0
  271. data/test/xml/test_dtd.rb +103 -0
  272. data/test/xml/test_dtd_encoding.rb +33 -0
  273. data/test/xml/test_element_content.rb +56 -0
  274. data/test/xml/test_element_decl.rb +73 -0
  275. data/test/xml/test_entity_decl.rb +122 -0
  276. data/test/xml/test_entity_reference.rb +235 -0
  277. data/test/xml/test_namespace.rb +75 -0
  278. data/test/xml/test_node.rb +1029 -0
  279. data/test/xml/test_node_attributes.rb +53 -0
  280. data/test/xml/test_node_encoding.rb +107 -0
  281. data/test/xml/test_node_inheritance.rb +32 -0
  282. data/test/xml/test_node_reparenting.rb +374 -0
  283. data/test/xml/test_node_set.rb +755 -0
  284. data/test/xml/test_parse_options.rb +64 -0
  285. data/test/xml/test_processing_instruction.rb +30 -0
  286. data/test/xml/test_reader_encoding.rb +142 -0
  287. data/test/xml/test_relax_ng.rb +60 -0
  288. data/test/xml/test_schema.rb +94 -0
  289. data/test/xml/test_syntax_error.rb +12 -0
  290. data/test/xml/test_text.rb +45 -0
  291. data/test/xml/test_unparented_node.rb +413 -0
  292. data/test/xml/test_xinclude.rb +83 -0
  293. data/test/xml/test_xpath.rb +295 -0
  294. data/test/xslt/test_custom_functions.rb +129 -0
  295. data/test/xslt/test_exception_handling.rb +37 -0
  296. data/test_all +84 -0
  297. metadata +571 -0
@@ -0,0 +1,13 @@
1
+ module Nokogiri
2
+ module XML
3
+ class ElementDecl < Nokogiri::XML::Node
4
+ undef_method :namespace
5
+ undef_method :namespace_definitions
6
+ undef_method :line if method_defined?(:line)
7
+
8
+ def inspect
9
+ "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module Nokogiri
2
+ module XML
3
+ class EntityDecl < Nokogiri::XML::Node
4
+ undef_method :attribute_nodes
5
+ undef_method :attributes
6
+ undef_method :namespace
7
+ undef_method :namespace_definitions
8
+ undef_method :line if method_defined?(:line)
9
+
10
+ def self.new name, doc, *args
11
+ doc.create_entity(name, *args)
12
+ end
13
+
14
+ def inspect
15
+ "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Nokogiri
2
+ module XML
3
+ class Namespace
4
+ include Nokogiri::XML::PP::Node
5
+ attr_reader :document
6
+
7
+ private
8
+ def inspect_attributes
9
+ [:prefix, :href]
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,946 @@
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
+ include Nokogiri::XML::PP::Node
38
+ include Enumerable
39
+
40
+ # Element node type, see Nokogiri::XML::Node#element?
41
+ ELEMENT_NODE = 1
42
+ # Attribute node type
43
+ ATTRIBUTE_NODE = 2
44
+ # Text node type, see Nokogiri::XML::Node#text?
45
+ TEXT_NODE = 3
46
+ # CDATA node type, see Nokogiri::XML::Node#cdata?
47
+ CDATA_SECTION_NODE = 4
48
+ # Entity reference node type
49
+ ENTITY_REF_NODE = 5
50
+ # Entity node type
51
+ ENTITY_NODE = 6
52
+ # PI node type
53
+ PI_NODE = 7
54
+ # Comment node type, see Nokogiri::XML::Node#comment?
55
+ COMMENT_NODE = 8
56
+ # Document node type, see Nokogiri::XML::Node#xml?
57
+ DOCUMENT_NODE = 9
58
+ # Document type node type
59
+ DOCUMENT_TYPE_NODE = 10
60
+ # Document fragment node type
61
+ DOCUMENT_FRAG_NODE = 11
62
+ # Notation node type
63
+ NOTATION_NODE = 12
64
+ # HTML document node type, see Nokogiri::XML::Node#html?
65
+ HTML_DOCUMENT_NODE = 13
66
+ # DTD node type
67
+ DTD_NODE = 14
68
+ # Element declaration type
69
+ ELEMENT_DECL = 15
70
+ # Attribute declaration type
71
+ ATTRIBUTE_DECL = 16
72
+ # Entity declaration type
73
+ ENTITY_DECL = 17
74
+ # Namespace declaration type
75
+ NAMESPACE_DECL = 18
76
+ # XInclude start type
77
+ XINCLUDE_START = 19
78
+ # XInclude end type
79
+ XINCLUDE_END = 20
80
+ # DOCB document node type
81
+ DOCB_DOCUMENT_NODE = 21
82
+
83
+ def initialize name, document # :nodoc:
84
+ # ... Ya. This is empty on purpose.
85
+ end
86
+
87
+ ###
88
+ # Decorate this node with the decorators set up in this node's Document
89
+ def decorate!
90
+ document.decorate(self)
91
+ end
92
+
93
+ ###
94
+ # Search this node for +paths+. +paths+ can be XPath or CSS, and an
95
+ # optional hash of namespaces may be appended.
96
+ # See Node#xpath and Node#css.
97
+ def search *paths
98
+ # TODO use paths, handler, ns, binds = extract_params(paths)
99
+ ns = paths.last.is_a?(Hash) ? paths.pop :
100
+ (document.root ? document.root.namespaces : {})
101
+
102
+ prefix = "#{implied_xpath_context}/"
103
+
104
+ xpath(*(paths.map { |path|
105
+ path = path.to_s
106
+ path =~ /^(\.\/|\/|\.\.|\.$)/ ? path : CSS.xpath_for(
107
+ path,
108
+ :prefix => prefix,
109
+ :ns => ns
110
+ )
111
+ }.flatten.uniq) + [ns])
112
+ end
113
+ alias :/ :search
114
+
115
+ ###
116
+ # call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
117
+ #
118
+ # Search this node for XPath +paths+. +paths+ must be one or more XPath
119
+ # queries.
120
+ #
121
+ # node.xpath('.//title')
122
+ #
123
+ # A hash of namespace bindings may be appended. For example:
124
+ #
125
+ # node.xpath('.//foo:name', {'foo' => 'http://example.org/'})
126
+ # node.xpath('.//xmlns:name', node.root.namespaces)
127
+ #
128
+ # A hash of variable bindings may also be appended to the namespace bindings. For example:
129
+ #
130
+ # node.xpath('.//address[@domestic=$value]', nil, {:value => 'Yes'})
131
+ #
132
+ # Custom XPath functions may also be defined. To define custom
133
+ # functions create a class and implement the function you want
134
+ # to define. The first argument to the method will be the
135
+ # current matching NodeSet. Any other arguments are ones that
136
+ # you pass in. Note that this class may appear anywhere in the
137
+ # argument list. For example:
138
+ #
139
+ # node.xpath('.//title[regex(., "\w+")]', Class.new {
140
+ # def regex node_set, regex
141
+ # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
142
+ # end
143
+ # }.new)
144
+ #
145
+ def xpath *paths
146
+ return NodeSet.new(document) unless document
147
+
148
+ paths, handler, ns, binds = extract_params(paths)
149
+
150
+ sets = paths.map { |path|
151
+ ctx = XPathContext.new(self)
152
+ ctx.register_namespaces(ns)
153
+ path = path.gsub(/xmlns:/, ' :') unless Nokogiri.uses_libxml?
154
+
155
+ binds.each do |key,value|
156
+ ctx.register_variable key.to_s, value
157
+ end if binds
158
+
159
+ ctx.evaluate(path, handler)
160
+ }
161
+ return sets.first if sets.length == 1
162
+
163
+ NodeSet.new(document) do |combined|
164
+ sets.each do |set|
165
+ set.each do |node|
166
+ combined << node
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ ###
173
+ # call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
174
+ #
175
+ # Search this node for CSS +rules+. +rules+ must be one or more CSS
176
+ # selectors. For example:
177
+ #
178
+ # node.css('title')
179
+ # node.css('body h1.bold')
180
+ # node.css('div + p.green', 'div#one')
181
+ #
182
+ # A hash of namespace bindings may be appended. For example:
183
+ #
184
+ # node.css('bike|tire', {'bike' => 'http://schwinn.com/'})
185
+ #
186
+ # Custom CSS pseudo classes may also be defined. To define
187
+ # custom pseudo classes, create a class and implement the custom
188
+ # pseudo class you want defined. The first argument to the
189
+ # method will be the current matching NodeSet. Any other
190
+ # arguments are ones that you pass in. For example:
191
+ #
192
+ # node.css('title:regex("\w+")', Class.new {
193
+ # def regex node_set, regex
194
+ # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
195
+ # end
196
+ # }.new)
197
+ #
198
+ # Note that the CSS query string is case-sensitive with regards
199
+ # to your document type. That is, if you're looking for "H1" in
200
+ # an HTML document, you'll never find anything, since HTML tags
201
+ # will match only lowercase CSS queries. However, "H1" might be
202
+ # found in an XML document, where tags names are case-sensitive
203
+ # (e.g., "H1" is distinct from "h1").
204
+ #
205
+ def css *rules
206
+ rules, handler, ns, binds = extract_params(rules)
207
+
208
+ prefix = "#{implied_xpath_context}/"
209
+
210
+ rules = rules.map { |rule|
211
+ CSS.xpath_for(rule, :prefix => prefix, :ns => ns)
212
+ }.flatten.uniq + [ns, handler, binds].compact
213
+
214
+ xpath(*rules)
215
+ end
216
+
217
+ ###
218
+ # Search this node's immediate children using CSS selector +selector+
219
+ def > selector
220
+ ns = document.root.namespaces
221
+ xpath CSS.xpath_for(selector, :prefix => "./", :ns => ns).first
222
+ end
223
+
224
+ ###
225
+ # Search for the first occurrence of +path+.
226
+ #
227
+ # Returns nil if nothing is found, otherwise a Node.
228
+ def at path, ns = document.root ? document.root.namespaces : {}
229
+ search(path, ns).first
230
+ end
231
+ alias :% :at
232
+
233
+ ##
234
+ # Search this node for the first occurrence of XPath +paths+.
235
+ # Equivalent to <tt>xpath(paths).first</tt>
236
+ # See Node#xpath for more information.
237
+ #
238
+ def at_xpath *paths
239
+ xpath(*paths).first
240
+ end
241
+
242
+ ##
243
+ # Search this node for the first occurrence of CSS +rules+.
244
+ # Equivalent to <tt>css(rules).first</tt>
245
+ # See Node#css for more information.
246
+ #
247
+ def at_css *rules
248
+ css(*rules).first
249
+ end
250
+
251
+ ###
252
+ # Get the attribute value for the attribute +name+
253
+ def [] name
254
+ return nil unless key?(name.to_s)
255
+ get(name.to_s)
256
+ end
257
+
258
+ ###
259
+ # Set the attribute value for the attribute +name+ to +value+
260
+ def []= name, value
261
+ set name.to_s, value
262
+ end
263
+
264
+ ###
265
+ # Add +node_or_tags+ as a child of this Node.
266
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
267
+ #
268
+ # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
269
+ #
270
+ # Also see related method +<<+.
271
+ def add_child node_or_tags
272
+ node_or_tags = coerce(node_or_tags)
273
+ if node_or_tags.is_a?(XML::NodeSet)
274
+ node_or_tags.each { |n| add_child_node n }
275
+ else
276
+ add_child_node node_or_tags
277
+ end
278
+ node_or_tags
279
+ end
280
+
281
+ ###
282
+ # Add +node_or_tags+ as a child of this Node.
283
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
284
+ #
285
+ # Returns self, to support chaining of calls (e.g., root << child1 << child2)
286
+ #
287
+ # Also see related method +add_child+.
288
+ def << node_or_tags
289
+ add_child node_or_tags
290
+ self
291
+ end
292
+ ###
293
+ # Insert +node_or_tags+ before this Node (as a sibling).
294
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
295
+ #
296
+ # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
297
+ #
298
+ # Also see related method +before+.
299
+ def add_previous_sibling node_or_tags
300
+ raise ArgumentError.new("A document may not have multiple root nodes.") if parent.is_a?(XML::Document) && !node_or_tags.is_a?(XML::ProcessingInstruction)
301
+
302
+ node_or_tags = coerce(node_or_tags)
303
+ if node_or_tags.is_a?(XML::NodeSet)
304
+ if text?
305
+ pivot = Nokogiri::XML::Node.new 'dummy', document
306
+ add_previous_sibling_node pivot
307
+ else
308
+ pivot = self
309
+ end
310
+ node_or_tags.each { |n| pivot.send :add_previous_sibling_node, n }
311
+ pivot.unlink if text?
312
+ else
313
+ add_previous_sibling_node node_or_tags
314
+ end
315
+ node_or_tags
316
+ end
317
+
318
+ ###
319
+ # Insert +node_or_tags+ after this Node (as a sibling).
320
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
321
+ #
322
+ # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
323
+ #
324
+ # Also see related method +after+.
325
+ def add_next_sibling node_or_tags
326
+ raise ArgumentError.new("A document may not have multiple root nodes.") if parent.is_a?(XML::Document)
327
+
328
+ node_or_tags = coerce(node_or_tags)
329
+ if node_or_tags.is_a?(XML::NodeSet)
330
+ if text?
331
+ pivot = Nokogiri::XML::Node.new 'dummy', document
332
+ add_next_sibling_node pivot
333
+ else
334
+ pivot = self
335
+ end
336
+ node_or_tags.reverse_each { |n| pivot.send :add_next_sibling_node, n }
337
+ pivot.unlink if text?
338
+ else
339
+ add_next_sibling_node node_or_tags
340
+ end
341
+ node_or_tags
342
+ end
343
+
344
+ ####
345
+ # Insert +node_or_tags+ before this node (as a sibling).
346
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
347
+ #
348
+ # Returns self, to support chaining of calls.
349
+ #
350
+ # Also see related method +add_previous_sibling+.
351
+ def before node_or_tags
352
+ add_previous_sibling node_or_tags
353
+ self
354
+ end
355
+
356
+ ####
357
+ # Insert +node_or_tags+ after this node (as a sibling).
358
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
359
+ #
360
+ # Returns self, to support chaining of calls.
361
+ #
362
+ # Also see related method +add_next_sibling+.
363
+ def after node_or_tags
364
+ add_next_sibling node_or_tags
365
+ self
366
+ end
367
+
368
+ ####
369
+ # Set the inner html for this Node to +node_or_tags+
370
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
371
+ #
372
+ # Returns self.
373
+ #
374
+ # Also see related method +children=+
375
+ def inner_html= node_or_tags
376
+ self.children = node_or_tags
377
+ self
378
+ end
379
+
380
+ ####
381
+ # Set the inner html for this Node +node_or_tags+
382
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a Nokogiri::XML::DocumentFragment, or a string containing markup.
383
+ #
384
+ # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
385
+ #
386
+ # Also see related method +inner_html=+
387
+ def children= node_or_tags
388
+ node_or_tags = coerce(node_or_tags)
389
+ children.unlink
390
+ if node_or_tags.is_a?(XML::NodeSet)
391
+ node_or_tags.each { |n| add_child_node n }
392
+ else
393
+ add_child_node node_or_tags
394
+ end
395
+ node_or_tags
396
+ end
397
+
398
+ ####
399
+ # Replace this Node with +node_or_tags+.
400
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
401
+ #
402
+ # Returns the reparented node (if +node_or_tags+ is a Node), or NodeSet (if +node_or_tags+ is a DocumentFragment, NodeSet, or string).
403
+ #
404
+ # Also see related method +swap+.
405
+ def replace node_or_tags
406
+ node_or_tags = coerce(node_or_tags)
407
+ if node_or_tags.is_a?(XML::NodeSet)
408
+ if text?
409
+ replacee = Nokogiri::XML::Node.new 'dummy', document
410
+ add_previous_sibling_node replacee
411
+ unlink
412
+ else
413
+ replacee = self
414
+ end
415
+ node_or_tags.each { |n| replacee.add_previous_sibling n }
416
+ replacee.unlink
417
+ else
418
+ replace_node node_or_tags
419
+ end
420
+ node_or_tags
421
+ end
422
+
423
+ ####
424
+ # Swap this Node for +node_or_tags+
425
+ # +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
426
+ #
427
+ # Returns self, to support chaining of calls.
428
+ #
429
+ # Also see related method +replace+.
430
+ def swap node_or_tags
431
+ replace node_or_tags
432
+ self
433
+ end
434
+
435
+ alias :next :next_sibling
436
+ alias :previous :previous_sibling
437
+
438
+ # :stopdoc:
439
+ # HACK: This is to work around an RDoc bug
440
+ alias :next= :add_next_sibling
441
+ # :startdoc:
442
+
443
+ alias :previous= :add_previous_sibling
444
+ alias :remove :unlink
445
+ alias :get_attribute :[]
446
+ alias :attr :[]
447
+ alias :set_attribute :[]=
448
+ alias :text :content
449
+ alias :inner_text :content
450
+ alias :has_attribute? :key?
451
+ alias :name :node_name
452
+ alias :name= :node_name=
453
+ alias :type :node_type
454
+ alias :to_str :text
455
+ alias :clone :dup
456
+ alias :elements :element_children
457
+
458
+ ####
459
+ # Returns a hash containing the node's attributes. The key is
460
+ # the attribute name without any namespace, the value is a Nokogiri::XML::Attr
461
+ # representing the attribute.
462
+ # If you need to distinguish attributes with the same name, with different namespaces
463
+ # use #attribute_nodes instead.
464
+ def attributes
465
+ Hash[attribute_nodes.map { |node|
466
+ [node.node_name, node]
467
+ }]
468
+ end
469
+
470
+ ###
471
+ # Get the attribute values for this Node.
472
+ def values
473
+ attribute_nodes.map { |node| node.value }
474
+ end
475
+
476
+ ###
477
+ # Get the attribute names for this Node.
478
+ def keys
479
+ attribute_nodes.map { |node| node.node_name }
480
+ end
481
+
482
+ ###
483
+ # Iterate over each attribute name and value pair for this Node.
484
+ def each
485
+ attribute_nodes.each { |node|
486
+ yield [node.node_name, node.value]
487
+ }
488
+ end
489
+
490
+ ###
491
+ # Remove the attribute named +name+
492
+ def remove_attribute name
493
+ attributes[name].remove if key? name
494
+ end
495
+ alias :delete :remove_attribute
496
+
497
+ ###
498
+ # Returns true if this Node matches +selector+
499
+ def matches? selector
500
+ ancestors.last.search(selector).include?(self)
501
+ end
502
+
503
+ ###
504
+ # Create a DocumentFragment containing +tags+ that is relative to _this_
505
+ # context node.
506
+ def fragment tags
507
+ type = document.html? ? Nokogiri::HTML : Nokogiri::XML
508
+ type::DocumentFragment.new(document, tags, self)
509
+ end
510
+
511
+ ###
512
+ # Parse +string_or_io+ as a document fragment within the context of
513
+ # *this* node. Returns a XML::NodeSet containing the nodes parsed from
514
+ # +string_or_io+.
515
+ def parse string_or_io, options = nil
516
+ options ||= (document.html? ? ParseOptions::DEFAULT_HTML : ParseOptions::DEFAULT_XML)
517
+ if Fixnum === options
518
+ options = Nokogiri::XML::ParseOptions.new(options)
519
+ end
520
+ # Give the options to the user
521
+ yield options if block_given?
522
+
523
+ contents = string_or_io.respond_to?(:read) ?
524
+ string_or_io.read :
525
+ string_or_io
526
+
527
+ return Nokogiri::XML::NodeSet.new(document) if contents.empty?
528
+
529
+ ##
530
+ # This is a horrible hack, but I don't care. See #313 for background.
531
+ error_count = document.errors.length
532
+ node_set = in_context(contents, options.to_i)
533
+ if node_set.empty? and document.errors.length > error_count and options.recover?
534
+ fragment = Nokogiri::HTML::DocumentFragment.parse contents
535
+ node_set = fragment.children
536
+ end
537
+ node_set
538
+ end
539
+
540
+ ####
541
+ # Set the Node's content to a Text node containing +string+. The string gets XML escaped, not interpreted as markup.
542
+ def content= string
543
+ self.native_content = encode_special_chars(string.to_s)
544
+ end
545
+
546
+ ###
547
+ # Set the parent Node for this Node
548
+ def parent= parent_node
549
+ parent_node.add_child(self)
550
+ parent_node
551
+ end
552
+
553
+ ###
554
+ # Returns a Hash of {prefix => value} for all namespaces on this
555
+ # node and its ancestors.
556
+ #
557
+ # This method returns the same namespaces as #namespace_scopes.
558
+ #
559
+ # Returns namespaces in scope for self -- those defined on self
560
+ # element directly or any ancestor node -- as a Hash of
561
+ # attribute-name/value pairs. Note that the keys in this hash
562
+ # XML attributes that would be used to define this namespace,
563
+ # such as "xmlns:prefix", not just the prefix. Default namespace
564
+ # set on self will be included with key "xmlns". However,
565
+ # default namespaces set on ancestor will NOT be, even if self
566
+ # has no explicit default namespace.
567
+ def namespaces
568
+ Hash[namespace_scopes.map { |nd|
569
+ key = ['xmlns', nd.prefix].compact.join(':')
570
+ if RUBY_VERSION >= '1.9' && document.encoding
571
+ begin
572
+ key.force_encoding document.encoding
573
+ rescue ArgumentError
574
+ end
575
+ end
576
+ [key, nd.href]
577
+ }]
578
+ end
579
+
580
+ # Returns true if this is a Comment
581
+ def comment?
582
+ type == COMMENT_NODE
583
+ end
584
+
585
+ # Returns true if this is a CDATA
586
+ def cdata?
587
+ type == CDATA_SECTION_NODE
588
+ end
589
+
590
+ # Returns true if this is an XML::Document node
591
+ def xml?
592
+ type == DOCUMENT_NODE
593
+ end
594
+
595
+ # Returns true if this is an HTML::Document node
596
+ def html?
597
+ type == HTML_DOCUMENT_NODE
598
+ end
599
+
600
+ # Returns true if this is a Text node
601
+ def text?
602
+ type == TEXT_NODE
603
+ end
604
+
605
+ # Returns true if this is a DocumentFragment
606
+ def fragment?
607
+ type == DOCUMENT_FRAG_NODE
608
+ end
609
+
610
+ ###
611
+ # Fetch the Nokogiri::HTML::ElementDescription for this node. Returns
612
+ # nil on XML documents and on unknown tags.
613
+ def description
614
+ return nil if document.xml?
615
+ Nokogiri::HTML::ElementDescription[name]
616
+ end
617
+
618
+ ###
619
+ # Is this a read only node?
620
+ def read_only?
621
+ # According to gdome2, these are read-only node types
622
+ [NOTATION_NODE, ENTITY_NODE, ENTITY_DECL].include?(type)
623
+ end
624
+
625
+ # Returns true if this is an Element node
626
+ def element?
627
+ type == ELEMENT_NODE
628
+ end
629
+ alias :elem? :element?
630
+
631
+ ###
632
+ # Turn this node in to a string. If the document is HTML, this method
633
+ # returns html. If the document is XML, this method returns XML.
634
+ def to_s
635
+ document.xml? ? to_xml : to_html
636
+ end
637
+
638
+ # Get the inner_html for this node's Node#children
639
+ def inner_html *args
640
+ children.map { |x| x.to_html(*args) }.join
641
+ end
642
+
643
+ # Get the path to this node as a CSS expression
644
+ def css_path
645
+ path.split(/\//).map { |part|
646
+ part.length == 0 ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)')
647
+ }.compact.join(' > ')
648
+ end
649
+
650
+ ###
651
+ # Get a list of ancestor Node for this Node. If +selector+ is given,
652
+ # the ancestors must match +selector+
653
+ def ancestors selector = nil
654
+ return NodeSet.new(document) unless respond_to?(:parent)
655
+ return NodeSet.new(document) unless parent
656
+
657
+ parents = [parent]
658
+
659
+ while parents.last.respond_to?(:parent)
660
+ break unless ctx_parent = parents.last.parent
661
+ parents << ctx_parent
662
+ end
663
+
664
+ return NodeSet.new(document, parents) unless selector
665
+
666
+ root = parents.last
667
+
668
+ NodeSet.new(document, parents.find_all { |parent|
669
+ root.search(selector).include?(parent)
670
+ })
671
+ end
672
+
673
+ ###
674
+ # Adds a default namespace supplied as a string +url+ href, to self.
675
+ # The consequence is as an xmlns attribute with supplied argument were
676
+ # present in parsed XML. A default namespace set with this method will
677
+ # now show up in #attributes, but when this node is serialized to XML an
678
+ # "xmlns" attribute will appear. See also #namespace and #namespace=
679
+ def default_namespace= url
680
+ add_namespace_definition(nil, url)
681
+ end
682
+ alias :add_namespace :add_namespace_definition
683
+
684
+ ###
685
+ # Set the default namespace on this node (as would be defined with an
686
+ # "xmlns=" attribute in XML source), as a Namespace object +ns+. Note that
687
+ # a Namespace added this way will NOT be serialized as an xmlns attribute
688
+ # for this node. You probably want #default_namespace= instead, or perhaps
689
+ # #add_namespace_definition with a nil prefix argument.
690
+ def namespace= ns
691
+ return set_namespace(ns) unless ns
692
+
693
+ unless Nokogiri::XML::Namespace === ns
694
+ raise TypeError, "#{ns.class} can't be coerced into Nokogiri::XML::Namespace"
695
+ end
696
+ if ns.document != document
697
+ raise ArgumentError, 'namespace must be declared on the same document'
698
+ end
699
+
700
+ set_namespace ns
701
+ end
702
+
703
+ ####
704
+ # Yields self and all children to +block+ recursively.
705
+ def traverse &block
706
+ children.each{|j| j.traverse(&block) }
707
+ block.call(self)
708
+ end
709
+
710
+ ###
711
+ # Accept a visitor. This method calls "visit" on +visitor+ with self.
712
+ def accept visitor
713
+ visitor.visit(self)
714
+ end
715
+
716
+ ###
717
+ # Test to see if this Node is equal to +other+
718
+ def == other
719
+ return false unless other
720
+ return false unless other.respond_to?(:pointer_id)
721
+ pointer_id == other.pointer_id
722
+ end
723
+
724
+ ###
725
+ # Serialize Node using +options+. Save options can also be set using a
726
+ # block. See SaveOptions.
727
+ #
728
+ # These two statements are equivalent:
729
+ #
730
+ # node.serialize(:encoding => 'UTF-8', :save_with => FORMAT | AS_XML)
731
+ #
732
+ # or
733
+ #
734
+ # node.serialize(:encoding => 'UTF-8') do |config|
735
+ # config.format.as_xml
736
+ # end
737
+ #
738
+ def serialize *args, &block
739
+ options = args.first.is_a?(Hash) ? args.shift : {
740
+ :encoding => args[0],
741
+ :save_with => args[1]
742
+ }
743
+
744
+ encoding = options[:encoding] || document.encoding
745
+ options[:encoding] = encoding
746
+
747
+ outstring = ""
748
+ if encoding && outstring.respond_to?(:force_encoding)
749
+ outstring.force_encoding(Encoding.find(encoding))
750
+ end
751
+ io = StringIO.new(outstring)
752
+ write_to io, options, &block
753
+ io.string
754
+ end
755
+
756
+ ###
757
+ # Serialize this Node to HTML
758
+ #
759
+ # doc.to_html
760
+ #
761
+ # See Node#write_to for a list of +options+. For formatted output,
762
+ # use Node#to_xhtml instead.
763
+ def to_html options = {}
764
+ # FIXME: this is a hack around broken libxml versions
765
+ return dump_html if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
766
+
767
+ options[:save_with] |= SaveOptions::DEFAULT_HTML if options[:save_with]
768
+ options[:save_with] = SaveOptions::DEFAULT_HTML unless options[:save_with]
769
+ serialize(options)
770
+ end
771
+
772
+ ###
773
+ # Serialize this Node to XML using +options+
774
+ #
775
+ # doc.to_xml(:indent => 5, :encoding => 'UTF-8')
776
+ #
777
+ # See Node#write_to for a list of +options+
778
+ def to_xml options = {}
779
+ options[:save_with] ||= SaveOptions::DEFAULT_XML
780
+ serialize(options)
781
+ end
782
+
783
+ ###
784
+ # Serialize this Node to XHTML using +options+
785
+ #
786
+ # doc.to_xhtml(:indent => 5, :encoding => 'UTF-8')
787
+ #
788
+ # See Node#write_to for a list of +options+
789
+ def to_xhtml options = {}
790
+ # FIXME: this is a hack around broken libxml versions
791
+ return dump_html if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
792
+
793
+ options[:save_with] |= SaveOptions::DEFAULT_XHTML if options[:save_with]
794
+ options[:save_with] = SaveOptions::DEFAULT_XHTML unless options[:save_with]
795
+ serialize(options)
796
+ end
797
+
798
+ ###
799
+ # Write Node to +io+ with +options+. +options+ modify the output of
800
+ # this method. Valid options are:
801
+ #
802
+ # * +:encoding+ for changing the encoding
803
+ # * +:indent_text+ the indentation text, defaults to one space
804
+ # * +:indent+ the number of +:indent_text+ to use, defaults to 2
805
+ # * +:save_with+ a combination of SaveOptions constants.
806
+ #
807
+ # To save with UTF-8 indented twice:
808
+ #
809
+ # node.write_to(io, :encoding => 'UTF-8', :indent => 2)
810
+ #
811
+ # To save indented with two dashes:
812
+ #
813
+ # node.write_to(io, :indent_text => '-', :indent => 2
814
+ #
815
+ def write_to io, *options
816
+ options = options.first.is_a?(Hash) ? options.shift : {}
817
+ encoding = options[:encoding] || options[0]
818
+ if Nokogiri.jruby?
819
+ save_options = options[:save_with] || options[1]
820
+ indent_times = options[:indent] || 0
821
+ else
822
+ save_options = options[:save_with] || options[1] || SaveOptions::FORMAT
823
+ indent_times = options[:indent] || 2
824
+ end
825
+ indent_text = options[:indent_text] || ' '
826
+
827
+ config = SaveOptions.new(save_options.to_i)
828
+ yield config if block_given?
829
+
830
+ native_write_to(io, encoding, indent_text * indent_times, config.options)
831
+ end
832
+
833
+ ###
834
+ # Write Node as HTML to +io+ with +options+
835
+ #
836
+ # See Node#write_to for a list of +options+
837
+ def write_html_to io, options = {}
838
+ # FIXME: this is a hack around broken libxml versions
839
+ return (io << dump_html) if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
840
+
841
+ options[:save_with] ||= SaveOptions::DEFAULT_HTML
842
+ write_to io, options
843
+ end
844
+
845
+ ###
846
+ # Write Node as XHTML to +io+ with +options+
847
+ #
848
+ # See Node#write_to for a list of +options+
849
+ def write_xhtml_to io, options = {}
850
+ # FIXME: this is a hack around broken libxml versions
851
+ return (io << dump_html) if Nokogiri.uses_libxml? && %w[2 6] === LIBXML_VERSION.split('.')[0..1]
852
+
853
+ options[:save_with] ||= SaveOptions::DEFAULT_XHTML
854
+ write_to io, options
855
+ end
856
+
857
+ ###
858
+ # Write Node as XML to +io+ with +options+
859
+ #
860
+ # doc.write_xml_to io, :encoding => 'UTF-8'
861
+ #
862
+ # See Node#write_to for a list of options
863
+ def write_xml_to io, options = {}
864
+ options[:save_with] ||= SaveOptions::DEFAULT_XML
865
+ write_to io, options
866
+ end
867
+
868
+ ###
869
+ # Compare two Node objects with respect to their Document. Nodes from
870
+ # different documents cannot be compared.
871
+ def <=> other
872
+ return nil unless other.is_a?(Nokogiri::XML::Node)
873
+ return nil unless document == other.document
874
+ compare other
875
+ end
876
+
877
+ ###
878
+ # Do xinclude substitution on the subtree below node. If given a block, a
879
+ # Nokogiri::XML::ParseOptions object initialized from +options+, will be
880
+ # passed to it, allowing more convenient modification of the parser options.
881
+ def do_xinclude options = XML::ParseOptions::DEFAULT_XML, &block
882
+ options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
883
+
884
+ # give options to user
885
+ yield options if block_given?
886
+
887
+ # call c extension
888
+ process_xincludes(options.to_i)
889
+ end
890
+
891
+ def canonicalize(mode=XML::XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false)
892
+ c14n_root = self
893
+ document.canonicalize(mode, inclusive_namespaces, with_comments) do |node, parent|
894
+ tn = node.is_a?(XML::Node) ? node : parent
895
+ tn == c14n_root || tn.ancestors.include?(c14n_root)
896
+ end
897
+ end
898
+
899
+ private
900
+
901
+ def extract_params params # :nodoc:
902
+ # Pop off our custom function handler if it exists
903
+ handler = params.find { |param|
904
+ ![Hash, String, Symbol].include?(param.class)
905
+ }
906
+
907
+ params -= [handler] if handler
908
+
909
+ hashes = []
910
+ while Hash === params.last || params.last.nil?
911
+ hashes << params.pop
912
+ break if params.empty?
913
+ end
914
+
915
+ ns, binds = hashes.reverse
916
+
917
+ ns ||= document.root ? document.root.namespaces : {}
918
+
919
+ [params, handler, ns, binds]
920
+ end
921
+
922
+ def coerce data # :nodoc:
923
+ return data if data.is_a?(XML::NodeSet)
924
+ return data.children if data.is_a?(XML::DocumentFragment)
925
+ return fragment(data).children if data.is_a?(String)
926
+
927
+ if data.is_a?(Document) || data.is_a?(XML::Attr) || !data.is_a?(XML::Node)
928
+ raise ArgumentError, <<-EOERR
929
+ Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
930
+ (You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
931
+ EOERR
932
+ end
933
+
934
+ data
935
+ end
936
+
937
+ def implied_xpath_context
938
+ "./"
939
+ end
940
+
941
+ def inspect_attributes
942
+ [:name, :namespace, :attribute_nodes, :children]
943
+ end
944
+ end
945
+ end
946
+ end