nokogiri-maglev- 1.5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. data/.autotest +26 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.ja.rdoc +544 -0
  4. data/CHANGELOG.rdoc +532 -0
  5. data/Manifest.txt +283 -0
  6. data/README.ja.rdoc +106 -0
  7. data/README.rdoc +174 -0
  8. data/Rakefile +171 -0
  9. data/bin/nokogiri +53 -0
  10. data/ext/nokogiri/depend +358 -0
  11. data/ext/nokogiri/extconf.rb +124 -0
  12. data/ext/nokogiri/html_document.c +154 -0
  13. data/ext/nokogiri/html_document.h +10 -0
  14. data/ext/nokogiri/html_element_description.c +276 -0
  15. data/ext/nokogiri/html_element_description.h +10 -0
  16. data/ext/nokogiri/html_entity_lookup.c +32 -0
  17. data/ext/nokogiri/html_entity_lookup.h +8 -0
  18. data/ext/nokogiri/html_sax_parser_context.c +94 -0
  19. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  20. data/ext/nokogiri/nokogiri.c +115 -0
  21. data/ext/nokogiri/nokogiri.h +160 -0
  22. data/ext/nokogiri/st.c +576 -0
  23. data/ext/nokogiri/xml_attr.c +94 -0
  24. data/ext/nokogiri/xml_attr.h +9 -0
  25. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  26. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  27. data/ext/nokogiri/xml_cdata.c +56 -0
  28. data/ext/nokogiri/xml_cdata.h +9 -0
  29. data/ext/nokogiri/xml_comment.c +54 -0
  30. data/ext/nokogiri/xml_comment.h +9 -0
  31. data/ext/nokogiri/xml_document.c +478 -0
  32. data/ext/nokogiri/xml_document.h +23 -0
  33. data/ext/nokogiri/xml_document_fragment.c +48 -0
  34. data/ext/nokogiri/xml_document_fragment.h +10 -0
  35. data/ext/nokogiri/xml_dtd.c +202 -0
  36. data/ext/nokogiri/xml_dtd.h +10 -0
  37. data/ext/nokogiri/xml_element_content.c +123 -0
  38. data/ext/nokogiri/xml_element_content.h +10 -0
  39. data/ext/nokogiri/xml_element_decl.c +69 -0
  40. data/ext/nokogiri/xml_element_decl.h +9 -0
  41. data/ext/nokogiri/xml_encoding_handler.c +79 -0
  42. data/ext/nokogiri/xml_encoding_handler.h +8 -0
  43. data/ext/nokogiri/xml_entity_decl.c +110 -0
  44. data/ext/nokogiri/xml_entity_decl.h +10 -0
  45. data/ext/nokogiri/xml_entity_reference.c +52 -0
  46. data/ext/nokogiri/xml_entity_reference.h +9 -0
  47. data/ext/nokogiri/xml_io.c +56 -0
  48. data/ext/nokogiri/xml_io.h +11 -0
  49. data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
  50. data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
  51. data/ext/nokogiri/xml_namespace.c +84 -0
  52. data/ext/nokogiri/xml_namespace.h +13 -0
  53. data/ext/nokogiri/xml_node.c +1397 -0
  54. data/ext/nokogiri/xml_node.h +13 -0
  55. data/ext/nokogiri/xml_node_set.c +418 -0
  56. data/ext/nokogiri/xml_node_set.h +9 -0
  57. data/ext/nokogiri/xml_processing_instruction.c +56 -0
  58. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  59. data/ext/nokogiri/xml_reader.c +684 -0
  60. data/ext/nokogiri/xml_reader.h +10 -0
  61. data/ext/nokogiri/xml_relax_ng.c +162 -0
  62. data/ext/nokogiri/xml_relax_ng.h +9 -0
  63. data/ext/nokogiri/xml_sax_parser.c +293 -0
  64. data/ext/nokogiri/xml_sax_parser.h +39 -0
  65. data/ext/nokogiri/xml_sax_parser_context.c +199 -0
  66. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  67. data/ext/nokogiri/xml_sax_push_parser.c +115 -0
  68. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  69. data/ext/nokogiri/xml_schema.c +205 -0
  70. data/ext/nokogiri/xml_schema.h +9 -0
  71. data/ext/nokogiri/xml_syntax_error.c +58 -0
  72. data/ext/nokogiri/xml_syntax_error.h +13 -0
  73. data/ext/nokogiri/xml_text.c +50 -0
  74. data/ext/nokogiri/xml_text.h +9 -0
  75. data/ext/nokogiri/xml_xpath_context.c +315 -0
  76. data/ext/nokogiri/xml_xpath_context.h +9 -0
  77. data/ext/nokogiri/xslt_stylesheet.c +265 -0
  78. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  79. data/lib/nokogiri.rb +127 -0
  80. data/lib/nokogiri/css.rb +27 -0
  81. data/lib/nokogiri/css/node.rb +99 -0
  82. data/lib/nokogiri/css/parser.rb +677 -0
  83. data/lib/nokogiri/css/parser.y +237 -0
  84. data/lib/nokogiri/css/parser_extras.rb +91 -0
  85. data/lib/nokogiri/css/syntax_error.rb +7 -0
  86. data/lib/nokogiri/css/tokenizer.rb +152 -0
  87. data/lib/nokogiri/css/tokenizer.rex +55 -0
  88. data/lib/nokogiri/css/xpath_visitor.rb +171 -0
  89. data/lib/nokogiri/decorators/slop.rb +35 -0
  90. data/lib/nokogiri/html.rb +36 -0
  91. data/lib/nokogiri/html/builder.rb +35 -0
  92. data/lib/nokogiri/html/document.rb +213 -0
  93. data/lib/nokogiri/html/document_fragment.rb +41 -0
  94. data/lib/nokogiri/html/element_description.rb +23 -0
  95. data/lib/nokogiri/html/element_description_defaults.rb +671 -0
  96. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  97. data/lib/nokogiri/html/sax/parser.rb +52 -0
  98. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  99. data/lib/nokogiri/syntax_error.rb +4 -0
  100. data/lib/nokogiri/version.rb +88 -0
  101. data/lib/nokogiri/xml.rb +67 -0
  102. data/lib/nokogiri/xml/attr.rb +14 -0
  103. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  104. data/lib/nokogiri/xml/builder.rb +426 -0
  105. data/lib/nokogiri/xml/cdata.rb +11 -0
  106. data/lib/nokogiri/xml/character_data.rb +7 -0
  107. data/lib/nokogiri/xml/document.rb +234 -0
  108. data/lib/nokogiri/xml/document_fragment.rb +98 -0
  109. data/lib/nokogiri/xml/dtd.rb +22 -0
  110. data/lib/nokogiri/xml/element_content.rb +36 -0
  111. data/lib/nokogiri/xml/element_decl.rb +13 -0
  112. data/lib/nokogiri/xml/entity_decl.rb +19 -0
  113. data/lib/nokogiri/xml/namespace.rb +13 -0
  114. data/lib/nokogiri/xml/node.rb +915 -0
  115. data/lib/nokogiri/xml/node/save_options.rb +61 -0
  116. data/lib/nokogiri/xml/node_set.rb +357 -0
  117. data/lib/nokogiri/xml/notation.rb +6 -0
  118. data/lib/nokogiri/xml/parse_options.rb +93 -0
  119. data/lib/nokogiri/xml/pp.rb +2 -0
  120. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  121. data/lib/nokogiri/xml/pp/node.rb +56 -0
  122. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  123. data/lib/nokogiri/xml/reader.rb +112 -0
  124. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  125. data/lib/nokogiri/xml/sax.rb +4 -0
  126. data/lib/nokogiri/xml/sax/document.rb +164 -0
  127. data/lib/nokogiri/xml/sax/parser.rb +115 -0
  128. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  129. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  130. data/lib/nokogiri/xml/schema.rb +63 -0
  131. data/lib/nokogiri/xml/syntax_error.rb +47 -0
  132. data/lib/nokogiri/xml/text.rb +9 -0
  133. data/lib/nokogiri/xml/xpath.rb +10 -0
  134. data/lib/nokogiri/xml/xpath/syntax_error.rb +11 -0
  135. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  136. data/lib/nokogiri/xslt.rb +52 -0
  137. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  138. data/lib/xsd/xmlparser/nokogiri.rb +90 -0
  139. data/nokogiri_help_responses.md +40 -0
  140. data/tasks/cross_compile.rb +152 -0
  141. data/tasks/nokogiri.org.rb +18 -0
  142. data/tasks/test.rb +94 -0
  143. data/test/css/test_nthiness.rb +159 -0
  144. data/test/css/test_parser.rb +303 -0
  145. data/test/css/test_tokenizer.rb +198 -0
  146. data/test/css/test_xpath_visitor.rb +85 -0
  147. data/test/decorators/test_slop.rb +16 -0
  148. data/test/files/2ch.html +108 -0
  149. data/test/files/address_book.rlx +12 -0
  150. data/test/files/address_book.xml +10 -0
  151. data/test/files/bar/bar.xsd +4 -0
  152. data/test/files/dont_hurt_em_why.xml +422 -0
  153. data/test/files/encoding.html +82 -0
  154. data/test/files/encoding.xhtml +84 -0
  155. data/test/files/exslt.xml +8 -0
  156. data/test/files/exslt.xslt +35 -0
  157. data/test/files/foo/foo.xsd +4 -0
  158. data/test/files/metacharset.html +10 -0
  159. data/test/files/noencoding.html +47 -0
  160. data/test/files/po.xml +32 -0
  161. data/test/files/po.xsd +66 -0
  162. data/test/files/shift_jis.html +10 -0
  163. data/test/files/shift_jis.xml +5 -0
  164. data/test/files/snuggles.xml +3 -0
  165. data/test/files/staff.dtd +10 -0
  166. data/test/files/staff.xml +59 -0
  167. data/test/files/staff.xslt +32 -0
  168. data/test/files/tlm.html +850 -0
  169. data/test/files/valid_bar.xml +2 -0
  170. data/test/helper.rb +173 -0
  171. data/test/html/sax/test_parser.rb +139 -0
  172. data/test/html/sax/test_parser_context.rb +48 -0
  173. data/test/html/test_builder.rb +165 -0
  174. data/test/html/test_document.rb +472 -0
  175. data/test/html/test_document_encoding.rb +138 -0
  176. data/test/html/test_document_fragment.rb +255 -0
  177. data/test/html/test_element_description.rb +101 -0
  178. data/test/html/test_named_characters.rb +14 -0
  179. data/test/html/test_node.rb +193 -0
  180. data/test/html/test_node_encoding.rb +27 -0
  181. data/test/test_convert_xpath.rb +135 -0
  182. data/test/test_css_cache.rb +45 -0
  183. data/test/test_encoding_handler.rb +46 -0
  184. data/test/test_memory_leak.rb +72 -0
  185. data/test/test_nokogiri.rb +133 -0
  186. data/test/test_reader.rb +425 -0
  187. data/test/test_soap4r_sax.rb +52 -0
  188. data/test/test_xslt_transforms.rb +193 -0
  189. data/test/xml/node/test_save_options.rb +28 -0
  190. data/test/xml/node/test_subclass.rb +44 -0
  191. data/test/xml/sax/test_parser.rb +338 -0
  192. data/test/xml/sax/test_parser_context.rb +113 -0
  193. data/test/xml/sax/test_push_parser.rb +156 -0
  194. data/test/xml/test_attr.rb +65 -0
  195. data/test/xml/test_attribute_decl.rb +86 -0
  196. data/test/xml/test_builder.rb +227 -0
  197. data/test/xml/test_cdata.rb +50 -0
  198. data/test/xml/test_comment.rb +29 -0
  199. data/test/xml/test_document.rb +697 -0
  200. data/test/xml/test_document_encoding.rb +26 -0
  201. data/test/xml/test_document_fragment.rb +192 -0
  202. data/test/xml/test_dtd.rb +107 -0
  203. data/test/xml/test_dtd_encoding.rb +33 -0
  204. data/test/xml/test_element_content.rb +56 -0
  205. data/test/xml/test_element_decl.rb +73 -0
  206. data/test/xml/test_entity_decl.rb +122 -0
  207. data/test/xml/test_entity_reference.rb +21 -0
  208. data/test/xml/test_namespace.rb +70 -0
  209. data/test/xml/test_node.rb +917 -0
  210. data/test/xml/test_node_attributes.rb +34 -0
  211. data/test/xml/test_node_encoding.rb +107 -0
  212. data/test/xml/test_node_reparenting.rb +334 -0
  213. data/test/xml/test_node_set.rb +742 -0
  214. data/test/xml/test_parse_options.rb +52 -0
  215. data/test/xml/test_processing_instruction.rb +30 -0
  216. data/test/xml/test_reader_encoding.rb +126 -0
  217. data/test/xml/test_relax_ng.rb +60 -0
  218. data/test/xml/test_schema.rb +94 -0
  219. data/test/xml/test_syntax_error.rb +12 -0
  220. data/test/xml/test_text.rb +47 -0
  221. data/test/xml/test_unparented_node.rb +381 -0
  222. data/test/xml/test_xpath.rb +237 -0
  223. data/test/xslt/test_custom_functions.rb +94 -0
  224. data/test/xslt/test_exception_handling.rb +37 -0
  225. metadata +548 -0
@@ -0,0 +1,13 @@
1
+ module Nokogiri
2
+ module HTML
3
+ class EntityDescription < Struct.new(:value, :name, :description); end
4
+
5
+ class EntityLookup
6
+ ###
7
+ # Look up entity with +name+
8
+ def [] name
9
+ (val = get(name)) && val.value
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ module Nokogiri
2
+ module HTML
3
+ ###
4
+ # Nokogiri lets you write a SAX parser to process HTML but get HTML
5
+ # correction features.
6
+ #
7
+ # See Nokogiri::HTML::SAX::Parser for a basic example of using a
8
+ # SAX parser with HTML.
9
+ #
10
+ # For more information on SAX parsers, see Nokogiri::XML::SAX
11
+ module SAX
12
+ ###
13
+ # This class lets you perform SAX style parsing on HTML with HTML
14
+ # error correction.
15
+ #
16
+ # Here is a basic usage example:
17
+ #
18
+ # class MyDoc < Nokogiri::XML::SAX::Document
19
+ # def start_element name, attributes = []
20
+ # puts "found a #{name}"
21
+ # end
22
+ # end
23
+ #
24
+ # parser = Nokogiri::HTML::SAX::Parser.new(MyDoc.new)
25
+ # parser.parse(File.read(ARGV[0], 'rb'))
26
+ #
27
+ # For more information on SAX parsers, see Nokogiri::XML::SAX
28
+ class Parser < Nokogiri::XML::SAX::Parser
29
+ ###
30
+ # Parse html stored in +data+ using +encoding+
31
+ def parse_memory data, encoding = 'UTF-8'
32
+ raise ArgumentError unless data
33
+ return unless data.length > 0
34
+ ctx = ParserContext.memory(data, encoding)
35
+ yield ctx if block_given?
36
+ ctx.parse_with self
37
+ end
38
+
39
+ ###
40
+ # Parse a file with +filename+
41
+ def parse_file filename, encoding = 'UTF-8'
42
+ raise ArgumentError unless filename
43
+ raise Errno::ENOENT unless File.exists?(filename)
44
+ raise Errno::EISDIR if File.directory?(filename)
45
+ ctx = ParserContext.file(filename, encoding)
46
+ yield ctx if block_given?
47
+ ctx.parse_with self
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,16 @@
1
+ module Nokogiri
2
+ module HTML
3
+ module SAX
4
+ ###
5
+ # Context for HTML SAX parsers. This class is usually not instantiated
6
+ # by the user. Instead, you should be looking at
7
+ # Nokogiri::HTML::SAX::Parser
8
+ class ParserContext < Nokogiri::XML::SAX::ParserContext
9
+ def self.new thing, encoding = 'UTF-8'
10
+ [:read, :close].all? { |x| thing.respond_to?(x) } ? super :
11
+ memory(thing, encoding)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module Nokogiri
2
+ class SyntaxError < ::StandardError
3
+ end
4
+ end
@@ -0,0 +1,88 @@
1
+ module Nokogiri
2
+ # The version of Nokogiri you are using
3
+ VERSION = '1.5.0.1'
4
+
5
+ class VersionInfo # :nodoc:
6
+ def jruby?
7
+ ::JRUBY_VERSION if RUBY_PLATFORM == "java"
8
+ end
9
+
10
+ def engine
11
+ defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'mri'
12
+ end
13
+
14
+ def loaded_parser_version
15
+ LIBXML_PARSER_VERSION.scan(/^(.*)(..)(..)$/).first.collect{ |j|
16
+ j.to_i
17
+ }.join(".")
18
+ end
19
+
20
+ def compiled_parser_version
21
+ LIBXML_VERSION
22
+ end
23
+
24
+ def libxml2?
25
+ defined?(LIBXML_VERSION)
26
+ end
27
+
28
+ def warnings
29
+ return [] unless libxml2?
30
+
31
+ if compiled_parser_version != loaded_parser_version
32
+ ["Nokogiri was built against LibXML version #{compiled_parser_version}, but has dynamically loaded #{loaded_parser_version}"]
33
+ else
34
+ []
35
+ end
36
+ end
37
+
38
+ def to_hash
39
+ hash_info = {}
40
+ hash_info['warnings'] = []
41
+ hash_info['nokogiri'] = Nokogiri::VERSION
42
+ hash_info['ruby'] = {}
43
+ hash_info['ruby']['version'] = ::RUBY_VERSION
44
+ hash_info['ruby']['platform'] = ::RUBY_PLATFORM
45
+ hash_info['ruby']['description'] = ::RUBY_DESCRIPTION
46
+ hash_info['ruby']['engine'] = engine
47
+ hash_info['ruby']['jruby'] = jruby? if jruby?
48
+
49
+ if libxml2?
50
+ hash_info['libxml'] = {}
51
+ hash_info['libxml']['binding'] = 'extension'
52
+ hash_info['libxml']['compiled'] = compiled_parser_version
53
+ hash_info['libxml']['loaded'] = loaded_parser_version
54
+ hash_info['warnings'] = warnings
55
+ end
56
+
57
+ hash_info
58
+ end
59
+
60
+ def to_markdown
61
+ begin
62
+ require 'psych'
63
+ rescue LoadError
64
+ end
65
+ require 'yaml'
66
+ "# Nokogiri (#{Nokogiri::VERSION})\n" +
67
+ YAML.dump(to_hash).each_line.map { |line| " #{line}" }.join
68
+ end
69
+
70
+ # FIXME: maybe switch to singleton?
71
+ @@instance = new
72
+ @@instance.warnings.each do |warning|
73
+ warn "WARNING: #{warning}"
74
+ end
75
+ def self.instance; @@instance; end
76
+ end
77
+
78
+ # More complete version information about libxml
79
+ VERSION_INFO = VersionInfo.instance.to_hash
80
+
81
+ def self.uses_libxml? # :nodoc:
82
+ VersionInfo.instance.libxml2?
83
+ end
84
+
85
+ def self.jruby? # :nodoc:
86
+ VersionInfo.instance.jruby?
87
+ end
88
+ end
@@ -0,0 +1,67 @@
1
+ require 'nokogiri/xml/pp'
2
+ require 'nokogiri/xml/parse_options'
3
+ require 'nokogiri/xml/sax'
4
+ require 'nokogiri/xml/node'
5
+ require 'nokogiri/xml/attribute_decl'
6
+ require 'nokogiri/xml/element_decl'
7
+ require 'nokogiri/xml/element_content'
8
+ require 'nokogiri/xml/character_data'
9
+ require 'nokogiri/xml/namespace'
10
+ require 'nokogiri/xml/attr'
11
+ require 'nokogiri/xml/dtd'
12
+ require 'nokogiri/xml/cdata'
13
+ require 'nokogiri/xml/text'
14
+ require 'nokogiri/xml/document'
15
+ require 'nokogiri/xml/document_fragment'
16
+ require 'nokogiri/xml/processing_instruction'
17
+ require 'nokogiri/xml/node_set'
18
+ require 'nokogiri/xml/syntax_error'
19
+ require 'nokogiri/xml/xpath'
20
+ require 'nokogiri/xml/xpath_context'
21
+ require 'nokogiri/xml/builder'
22
+ require 'nokogiri/xml/reader'
23
+ require 'nokogiri/xml/notation'
24
+ require 'nokogiri/xml/entity_decl'
25
+ require 'nokogiri/xml/schema'
26
+ require 'nokogiri/xml/relax_ng'
27
+
28
+ module Nokogiri
29
+ class << self
30
+ ###
31
+ # Parse XML. Convenience method for Nokogiri::XML::Document.parse
32
+ def XML thing, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_XML, &block
33
+ Nokogiri::XML::Document.parse(thing, url, encoding, options, &block)
34
+ end
35
+ end
36
+
37
+ module XML
38
+ class << self
39
+ ###
40
+ # Parse an XML document using the Nokogiri::XML::Reader API. See
41
+ # Nokogiri::XML::Reader for mor information
42
+ def Reader string_or_io, url = nil, encoding = nil, options = ParseOptions::STRICT
43
+
44
+ options = Nokogiri::XML::ParseOptions.new(options) if Fixnum === options
45
+ # Give the options to the user
46
+ yield options if block_given?
47
+
48
+ if string_or_io.respond_to? :read
49
+ return Reader.from_io(string_or_io, url, encoding, options.to_i)
50
+ end
51
+ Reader.from_memory(string_or_io, url, encoding, options.to_i)
52
+ end
53
+
54
+ ###
55
+ # Parse XML. Convenience method for Nokogiri::XML::Document.parse
56
+ def parse thing, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML, &block
57
+ Document.parse(thing, url, encoding, options, &block)
58
+ end
59
+
60
+ ####
61
+ # Parse a fragment from +string+ in to a NodeSet.
62
+ def fragment string
63
+ XML::DocumentFragment.parse(string)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,14 @@
1
+ module Nokogiri
2
+ module XML
3
+ class Attr < Node
4
+ alias :value :content
5
+ alias :to_s :content
6
+ alias :content= :value=
7
+
8
+ private
9
+ def inspect_attributes
10
+ [:name, :namespace, :value]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Nokogiri
2
+ module XML
3
+ ###
4
+ # Represents an attribute declaration in a DTD
5
+ class AttributeDecl < Nokogiri::XML::Node
6
+ undef_method :attribute_nodes
7
+ undef_method :attributes
8
+ undef_method :content
9
+ undef_method :namespace
10
+ undef_method :namespace_definitions
11
+ undef_method :line if method_defined?(:line)
12
+
13
+ def inspect
14
+ "#<#{self.class.name}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,426 @@
1
+ module Nokogiri
2
+ module XML
3
+ ###
4
+ # Nokogiri builder can be used for building XML and HTML documents.
5
+ #
6
+ # == Synopsis:
7
+ #
8
+ # builder = Nokogiri::XML::Builder.new do |xml|
9
+ # xml.root {
10
+ # xml.products {
11
+ # xml.widget {
12
+ # xml.id_ "10"
13
+ # xml.name "Awesome widget"
14
+ # }
15
+ # }
16
+ # }
17
+ # end
18
+ # puts builder.to_xml
19
+ #
20
+ # Will output:
21
+ #
22
+ # <?xml version="1.0"?>
23
+ # <root>
24
+ # <products>
25
+ # <widget>
26
+ # <id>10</id>
27
+ # <name>Awesome widget</name>
28
+ # </widget>
29
+ # </products>
30
+ # </root>
31
+ #
32
+ #
33
+ # === Builder scope
34
+ #
35
+ # The builder allows two forms. When the builder is supplied with a block
36
+ # that has a parameter, the outside scope is maintained. This means you
37
+ # can access variables that are outside your builder. If you don't need
38
+ # outside scope, you can use the builder without the "xml" prefix like
39
+ # this:
40
+ #
41
+ # builder = Nokogiri::XML::Builder.new do
42
+ # root {
43
+ # products {
44
+ # widget {
45
+ # id_ "10"
46
+ # name "Awesome widget"
47
+ # }
48
+ # }
49
+ # }
50
+ # end
51
+ #
52
+ # == Special Tags
53
+ #
54
+ # The builder works by taking advantage of method_missing. Unfortunately
55
+ # some methods are defined in ruby that are difficult or dangerous to
56
+ # remove. You may want to create tags with the name "type", "class", and
57
+ # "id" for example. In that case, you can use an underscore to
58
+ # disambiguate your tag name from the method call.
59
+ #
60
+ # Here is an example of using the underscore to disambiguate tag names from
61
+ # ruby methods:
62
+ #
63
+ # @objects = [Object.new, Object.new, Object.new]
64
+ #
65
+ # builder = Nokogiri::XML::Builder.new do |xml|
66
+ # xml.root {
67
+ # xml.objects {
68
+ # @objects.each do |o|
69
+ # xml.object {
70
+ # xml.type_ o.type
71
+ # xml.class_ o.class.name
72
+ # xml.id_ o.id
73
+ # }
74
+ # end
75
+ # }
76
+ # }
77
+ # end
78
+ # puts builder.to_xml
79
+ #
80
+ # The underscore may be used with any tag name, and the last underscore
81
+ # will just be removed. This code will output the following XML:
82
+ #
83
+ # <?xml version="1.0"?>
84
+ # <root>
85
+ # <objects>
86
+ # <object>
87
+ # <type>Object</type>
88
+ # <class>Object</class>
89
+ # <id>48390</id>
90
+ # </object>
91
+ # <object>
92
+ # <type>Object</type>
93
+ # <class>Object</class>
94
+ # <id>48380</id>
95
+ # </object>
96
+ # <object>
97
+ # <type>Object</type>
98
+ # <class>Object</class>
99
+ # <id>48370</id>
100
+ # </object>
101
+ # </objects>
102
+ # </root>
103
+ #
104
+ # == Tag Attributes
105
+ #
106
+ # Tag attributes may be supplied as method arguments. Here is our
107
+ # previous example, but using attributes rather than tags:
108
+ #
109
+ # @objects = [Object.new, Object.new, Object.new]
110
+ #
111
+ # builder = Nokogiri::XML::Builder.new do |xml|
112
+ # xml.root {
113
+ # xml.objects {
114
+ # @objects.each do |o|
115
+ # xml.object(:type => o.type, :class => o.class, :id => o.id)
116
+ # end
117
+ # }
118
+ # }
119
+ # end
120
+ # puts builder.to_xml
121
+ #
122
+ # === Tag Attribute Short Cuts
123
+ #
124
+ # A couple attribute short cuts are available when building tags. The
125
+ # short cuts are available by special method calls when building a tag.
126
+ #
127
+ # This example builds an "object" tag with the class attribute "classy"
128
+ # and the id of "thing":
129
+ #
130
+ # builder = Nokogiri::XML::Builder.new do |xml|
131
+ # xml.root {
132
+ # xml.objects {
133
+ # xml.object.classy.thing!
134
+ # }
135
+ # }
136
+ # end
137
+ # puts builder.to_xml
138
+ #
139
+ # Which will output:
140
+ #
141
+ # <?xml version="1.0"?>
142
+ # <root>
143
+ # <objects>
144
+ # <object class="classy" id="thing"/>
145
+ # </objects>
146
+ # </root>
147
+ #
148
+ # All other options are still supported with this syntax, including
149
+ # blocks and extra tag attributes.
150
+ #
151
+ # == Namespaces
152
+ #
153
+ # Namespaces are added similarly to attributes. Nokogiri::XML::Builder
154
+ # assumes that when an attribute starts with "xmlns", it is meant to be
155
+ # a namespace:
156
+ #
157
+ # builder = Nokogiri::XML::Builder.new { |xml|
158
+ # xml.root('xmlns' => 'default', 'xmlns:foo' => 'bar') do
159
+ # xml.tenderlove
160
+ # end
161
+ # }
162
+ # puts builder.to_xml
163
+ #
164
+ # Will output XML like this:
165
+ #
166
+ # <?xml version="1.0"?>
167
+ # <root xmlns:foo="bar" xmlns="default">
168
+ # <tenderlove/>
169
+ # </root>
170
+ #
171
+ # === Referencing declared namespaces
172
+ #
173
+ # Tags that reference non-default namespaces (i.e. a tag "foo:bar") can be
174
+ # built by using the Nokogiri::XML::Builder#[] method.
175
+ #
176
+ # For example:
177
+ #
178
+ # builder = Nokogiri::XML::Builder.new do |xml|
179
+ # xml.root('xmlns:foo' => 'bar') {
180
+ # xml.objects {
181
+ # xml['foo'].object.classy.thing!
182
+ # }
183
+ # }
184
+ # end
185
+ # puts builder.to_xml
186
+ #
187
+ # Will output this XML:
188
+ #
189
+ # <?xml version="1.0"?>
190
+ # <root xmlns:foo="bar">
191
+ # <objects>
192
+ # <foo:object class="classy" id="thing"/>
193
+ # </objects>
194
+ # </root>
195
+ #
196
+ # Note the "foo:object" tag.
197
+ #
198
+ # == Document Types
199
+ #
200
+ # To create a document type (DTD), access use the Builder#doc method to get
201
+ # the current context document. Then call Node#create_internal_subset to
202
+ # create the DTD node.
203
+ #
204
+ # For example, this Ruby:
205
+ #
206
+ # builder = Nokogiri::XML::Builder.new do |xml|
207
+ # xml.doc.create_internal_subset(
208
+ # 'html',
209
+ # "-//W3C//DTD HTML 4.01 Transitional//EN",
210
+ # "http://www.w3.org/TR/html4/loose.dtd"
211
+ # )
212
+ # xml.root do
213
+ # xml.foo
214
+ # end
215
+ # end
216
+ #
217
+ # puts builder.to_xml
218
+ #
219
+ # Will output this xml:
220
+ #
221
+ # <?xml version="1.0"?>
222
+ # <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
223
+ # <root>
224
+ # <foo/>
225
+ # </root>
226
+ #
227
+ class Builder
228
+ # The current Document object being built
229
+ attr_accessor :doc
230
+
231
+ # The parent of the current node being built
232
+ attr_accessor :parent
233
+
234
+ # A context object for use when the block has no arguments
235
+ attr_accessor :context
236
+
237
+ attr_accessor :arity # :nodoc:
238
+
239
+ ###
240
+ # Create a builder with an existing root object. This is for use when
241
+ # you have an existing document that you would like to augment with
242
+ # builder methods. The builder context created will start with the
243
+ # given +root+ node.
244
+ #
245
+ # For example:
246
+ #
247
+ # doc = Nokogiri::XML(open('somedoc.xml'))
248
+ # Nokogiri::XML::Builder.with(doc.at('some_tag')) do |xml|
249
+ # # ... Use normal builder methods here ...
250
+ # xml.awesome # add the "awesome" tag below "some_tag"
251
+ # end
252
+ #
253
+ def self.with root, &block
254
+ new({}, root, &block)
255
+ end
256
+
257
+ ###
258
+ # Create a new Builder object. +options+ are sent to the top level
259
+ # Document that is being built.
260
+ #
261
+ # Building a document with a particular encoding for example:
262
+ #
263
+ # Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
264
+ # ...
265
+ # end
266
+ def initialize options = {}, root = nil, &block
267
+
268
+ if root
269
+ @doc = root.document
270
+ @parent = root
271
+ else
272
+ namespace = self.class.name.split('::')
273
+ namespace[-1] = 'Document'
274
+ @doc = eval(namespace.join('::')).new
275
+ @parent = @doc
276
+ end
277
+
278
+ @context = nil
279
+ @arity = nil
280
+ @ns = nil
281
+
282
+ options.each do |k,v|
283
+ @doc.send(:"#{k}=", v)
284
+ end
285
+
286
+ return unless block_given?
287
+
288
+ @arity = block.arity
289
+ if @arity <= 0
290
+ # @context = eval('self', block.binding)
291
+ @context = block.__get_self # maglev workaround
292
+ instance_eval(&block)
293
+ else
294
+ yield self
295
+ end
296
+
297
+ @parent = @doc
298
+ end
299
+
300
+ ###
301
+ # Create a Text Node with content of +string+
302
+ def text string
303
+ insert @doc.create_text_node(string)
304
+ end
305
+
306
+ ###
307
+ # Create a CDATA Node with content of +string+
308
+ def cdata string
309
+ insert(doc.create_cdata(string))
310
+ end
311
+
312
+ ###
313
+ # Build a tag that is associated with namespace +ns+. Raises an
314
+ # ArgumentError if +ns+ has not been defined higher in the tree.
315
+ def [] ns
316
+ @ns = @parent.namespace_definitions.find { |x| x.prefix == ns.to_s }
317
+ return self if @ns
318
+
319
+ @parent.ancestors.each do |a|
320
+ next if a == doc
321
+ @ns = a.namespace_definitions.find { |x| x.prefix == ns.to_s }
322
+ return self if @ns
323
+ end
324
+
325
+ raise ArgumentError, "Namespace #{ns} has not been defined"
326
+ end
327
+
328
+ ###
329
+ # Convert this Builder object to XML
330
+ def to_xml(*args)
331
+ if Nokogiri.jruby?
332
+ options = args.first.is_a?(Hash) ? args.shift : {}
333
+ if !options[:save_with]
334
+ options[:save_with] = Node::SaveOptions::AS_BUILDER
335
+ end
336
+ args.insert(0, options)
337
+ end
338
+ @doc.to_xml(*args)
339
+ end
340
+
341
+ ###
342
+ # Append the given raw XML +string+ to the document
343
+ def << string
344
+ @doc.fragment(string).children.each { |x| insert(x) }
345
+ end
346
+
347
+ def method_missing method, *args, &block # :nodoc:
348
+ if @context && @context.respond_to?(method)
349
+ @context.send(method, *args, &block)
350
+ else
351
+ node = @doc.create_element(method.to_s.sub(/[_!]$/, ''),*args) { |n|
352
+ # Set up the namespace
353
+ if @ns
354
+ n.namespace = @ns
355
+ @ns = nil
356
+ end
357
+ }
358
+ insert(node, &block)
359
+ end
360
+ end
361
+
362
+ private
363
+ ###
364
+ # Insert +node+ as a child of the current Node
365
+ def insert(node, &block)
366
+ node.parent = @parent
367
+ if block_given?
368
+ old_parent = @parent
369
+ @parent = node
370
+ @arity ||= block.arity
371
+ if @arity <= 0
372
+ instance_eval(&block)
373
+ else
374
+ block.call(self)
375
+ end
376
+ @parent = old_parent
377
+ end
378
+ NodeBuilder.new(node, self)
379
+ end
380
+
381
+ class NodeBuilder # :nodoc:
382
+ def initialize node, doc_builder
383
+ @node = node
384
+ @doc_builder = doc_builder
385
+ end
386
+
387
+ def []= k, v
388
+ @node[k] = v
389
+ end
390
+
391
+ def [] k
392
+ @node[k]
393
+ end
394
+
395
+ def method_missing(method, *args, &block)
396
+ opts = args.last.is_a?(Hash) ? args.pop : {}
397
+ case method.to_s
398
+ when /^(.*)!$/
399
+ @node['id'] = $1
400
+ @node.content = args.first if args.first
401
+ when /^(.*)=/
402
+ @node[$1] = args.first
403
+ else
404
+ @node['class'] =
405
+ ((@node['class'] || '').split(/\s/) + [method.to_s]).join(' ')
406
+ @node.content = args.first if args.first
407
+ end
408
+
409
+ # Assign any extra options
410
+ opts.each do |k,v|
411
+ @node[k.to_s] = ((@node[k.to_s] || '').split(/\s/) + [v]).join(' ')
412
+ end
413
+
414
+ if block_given?
415
+ old_parent = @doc_builder.parent
416
+ @doc_builder.parent = @node
417
+ value = @doc_builder.instance_eval(&block)
418
+ @doc_builder.parent = old_parent
419
+ return value
420
+ end
421
+ self
422
+ end
423
+ end
424
+ end
425
+ end
426
+ end