magic_xml 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (287) hide show
  1. data/README +22 -0
  2. data/Rakefile +52 -0
  3. data/VERSION +1 -0
  4. data/doc/classes/Array.html +148 -0
  5. data/doc/classes/File.html +113 -0
  6. data/doc/classes/Hash.html +117 -0
  7. data/doc/classes/Patterns_all.html +145 -0
  8. data/doc/classes/Patterns_any.html +145 -0
  9. data/doc/classes/String.html +470 -0
  10. data/doc/classes/Symbol.html +145 -0
  11. data/doc/classes/XML.html +1881 -0
  12. data/doc/classes/XML_Comment.html +148 -0
  13. data/doc/classes/XML_PI.html +145 -0
  14. data/doc/classes/XML_Tests.html +1727 -0
  15. data/doc/files/magic_xml_rb.html +186 -0
  16. data/doc/files/simple_examples/xml_hello_f_rb.html +88 -0
  17. data/doc/files/simple_examples/xml_hello_m_rb.html +88 -0
  18. data/doc/files/simple_examples/xml_list_f_rb.html +88 -0
  19. data/doc/files/simple_examples/xml_list_m_rb.html +88 -0
  20. data/doc/files/tests_rb.html +94 -0
  21. data/doc/files/xquery_use_cases/parts/q1_rb.html +117 -0
  22. data/doc/files/xquery_use_cases/rdb/q10_rb.html +88 -0
  23. data/doc/files/xquery_use_cases/rdb/q11_rb.html +88 -0
  24. data/doc/files/xquery_use_cases/rdb/q12_rb.html +88 -0
  25. data/doc/files/xquery_use_cases/rdb/q13_rb.html +88 -0
  26. data/doc/files/xquery_use_cases/rdb/q14_rb.html +88 -0
  27. data/doc/files/xquery_use_cases/rdb/q15_rb.html +88 -0
  28. data/doc/files/xquery_use_cases/rdb/q16_rb.html +88 -0
  29. data/doc/files/xquery_use_cases/rdb/q17_rb.html +88 -0
  30. data/doc/files/xquery_use_cases/rdb/q18_rb.html +88 -0
  31. data/doc/files/xquery_use_cases/rdb/q1_rb.html +88 -0
  32. data/doc/files/xquery_use_cases/rdb/q2_rb.html +88 -0
  33. data/doc/files/xquery_use_cases/rdb/q3_rb.html +88 -0
  34. data/doc/files/xquery_use_cases/rdb/q4_rb.html +88 -0
  35. data/doc/files/xquery_use_cases/rdb/q5_rb.html +88 -0
  36. data/doc/files/xquery_use_cases/rdb/q6_rb.html +88 -0
  37. data/doc/files/xquery_use_cases/rdb/q7_rb.html +88 -0
  38. data/doc/files/xquery_use_cases/rdb/q8_rb.html +88 -0
  39. data/doc/files/xquery_use_cases/rdb/q9_rb.html +88 -0
  40. data/doc/files/xquery_use_cases/seq/q1_rb.html +88 -0
  41. data/doc/files/xquery_use_cases/seq/q2_rb.html +88 -0
  42. data/doc/files/xquery_use_cases/seq/q3_rb.html +88 -0
  43. data/doc/files/xquery_use_cases/seq/q4_rb.html +88 -0
  44. data/doc/files/xquery_use_cases/seq/q5_rb.html +88 -0
  45. data/doc/files/xquery_use_cases/sgml/q10_rb.html +88 -0
  46. data/doc/files/xquery_use_cases/sgml/q1_rb.html +88 -0
  47. data/doc/files/xquery_use_cases/sgml/q2_rb.html +88 -0
  48. data/doc/files/xquery_use_cases/sgml/q3_rb.html +88 -0
  49. data/doc/files/xquery_use_cases/sgml/q4_rb.html +88 -0
  50. data/doc/files/xquery_use_cases/sgml/q5_rb.html +88 -0
  51. data/doc/files/xquery_use_cases/sgml/q6_rb.html +88 -0
  52. data/doc/files/xquery_use_cases/sgml/q7_rb.html +88 -0
  53. data/doc/files/xquery_use_cases/sgml/q8a_rb.html +88 -0
  54. data/doc/files/xquery_use_cases/sgml/q8b_rb.html +88 -0
  55. data/doc/files/xquery_use_cases/sgml/q9_rb.html +88 -0
  56. data/doc/files/xquery_use_cases/solution_sizes_rb.html +88 -0
  57. data/doc/files/xquery_use_cases/string/q1_rb.html +88 -0
  58. data/doc/files/xquery_use_cases/string/q2_rb.html +93 -0
  59. data/doc/files/xquery_use_cases/string/q4_rb.html +88 -0
  60. data/doc/files/xquery_use_cases/string/q5_rb.html +88 -0
  61. data/doc/files/xquery_use_cases/test_driver_rb.html +92 -0
  62. data/doc/files/xquery_use_cases/tree/q1_rb.html +111 -0
  63. data/doc/files/xquery_use_cases/tree/q2_rb.html +88 -0
  64. data/doc/files/xquery_use_cases/tree/q3_rb.html +88 -0
  65. data/doc/files/xquery_use_cases/tree/q4_rb.html +88 -0
  66. data/doc/files/xquery_use_cases/tree/q5_rb.html +88 -0
  67. data/doc/files/xquery_use_cases/tree/q6_rb.html +113 -0
  68. data/doc/files/xquery_use_cases/xmp/q10_rb.html +88 -0
  69. data/doc/files/xquery_use_cases/xmp/q11_rb.html +88 -0
  70. data/doc/files/xquery_use_cases/xmp/q12_rb.html +88 -0
  71. data/doc/files/xquery_use_cases/xmp/q1_rb.html +88 -0
  72. data/doc/files/xquery_use_cases/xmp/q2_rb.html +88 -0
  73. data/doc/files/xquery_use_cases/xmp/q3_rb.html +88 -0
  74. data/doc/files/xquery_use_cases/xmp/q4_rb.html +88 -0
  75. data/doc/files/xquery_use_cases/xmp/q5_rb.html +92 -0
  76. data/doc/files/xquery_use_cases/xmp/q6_rb.html +88 -0
  77. data/doc/files/xquery_use_cases/xmp/q7_rb.html +88 -0
  78. data/doc/files/xquery_use_cases/xmp/q8_rb.html +88 -0
  79. data/doc/files/xquery_use_cases/xmp/q9_rb.html +88 -0
  80. data/doc/fr_class_index.html +56 -0
  81. data/doc/fr_file_index.html +110 -0
  82. data/doc/fr_method_index.html +159 -0
  83. data/doc/index.html +26 -0
  84. data/doc/rdoc-style.css +175 -0
  85. data/lib/magic_xml.rb +1400 -0
  86. data/simple_examples/README +14 -0
  87. data/simple_examples/xml_hello_f.rb +32 -0
  88. data/simple_examples/xml_hello_m.rb +32 -0
  89. data/simple_examples/xml_list_f.rb +36 -0
  90. data/simple_examples/xml_list_m.rb +36 -0
  91. data/test/helper.rb +9 -0
  92. data/test/test_magic_xml.rb +855 -0
  93. data/xquery_use_cases/README +17 -0
  94. data/xquery_use_cases/parts/README +12 -0
  95. data/xquery_use_cases/parts/partlist.xml +13 -0
  96. data/xquery_use_cases/parts/q1.out +16 -0
  97. data/xquery_use_cases/parts/q1.rb +38 -0
  98. data/xquery_use_cases/parts/q1.xquery +18 -0
  99. data/xquery_use_cases/rdb/README +50 -0
  100. data/xquery_use_cases/rdb/bids.xml +81 -0
  101. data/xquery_use_cases/rdb/items.xml +57 -0
  102. data/xquery_use_cases/rdb/q1.out +10 -0
  103. data/xquery_use_cases/rdb/q1.rb +31 -0
  104. data/xquery_use_cases/rdb/q1.xquery +14 -0
  105. data/xquery_use_cases/rdb/q10.out +27 -0
  106. data/xquery_use_cases/rdb/q10.rb +37 -0
  107. data/xquery_use_cases/rdb/q10.xquery +15 -0
  108. data/xquery_use_cases/rdb/q11.out +7 -0
  109. data/xquery_use_cases/rdb/q11.rb +38 -0
  110. data/xquery_use_cases/rdb/q11.xquery +15 -0
  111. data/xquery_use_cases/rdb/q12.out +12 -0
  112. data/xquery_use_cases/rdb/q12.rb +42 -0
  113. data/xquery_use_cases/rdb/q12.xquery +28 -0
  114. data/xquery_use_cases/rdb/q13.out +32 -0
  115. data/xquery_use_cases/rdb/q13.rb +45 -0
  116. data/xquery_use_cases/rdb/q13.xquery +15 -0
  117. data/xquery_use_cases/rdb/q14.out +14 -0
  118. data/xquery_use_cases/rdb/q14.rb +42 -0
  119. data/xquery_use_cases/rdb/q14.xquery +14 -0
  120. data/xquery_use_cases/rdb/q15.out +5 -0
  121. data/xquery_use_cases/rdb/q15.rb +31 -0
  122. data/xquery_use_cases/rdb/q15.xquery +9 -0
  123. data/xquery_use_cases/rdb/q16.out +35 -0
  124. data/xquery_use_cases/rdb/q16.rb +35 -0
  125. data/xquery_use_cases/rdb/q16.xquery +17 -0
  126. data/xquery_use_cases/rdb/q17.out +1 -0
  127. data/xquery_use_cases/rdb/q17.rb +35 -0
  128. data/xquery_use_cases/rdb/q17.xquery +11 -0
  129. data/xquery_use_cases/rdb/q18.out +32 -0
  130. data/xquery_use_cases/rdb/q18.rb +40 -0
  131. data/xquery_use_cases/rdb/q18.xquery +19 -0
  132. data/xquery_use_cases/rdb/q2.out +22 -0
  133. data/xquery_use_cases/rdb/q2.rb +36 -0
  134. data/xquery_use_cases/rdb/q2.xquery +14 -0
  135. data/xquery_use_cases/rdb/q3.out +8 -0
  136. data/xquery_use_cases/rdb/q3.rb +34 -0
  137. data/xquery_use_cases/rdb/q3.xquery +16 -0
  138. data/xquery_use_cases/rdb/q4.out +14 -0
  139. data/xquery_use_cases/rdb/q4.rb +31 -0
  140. data/xquery_use_cases/rdb/q4.xquery +11 -0
  141. data/xquery_use_cases/rdb/q5.out +12 -0
  142. data/xquery_use_cases/rdb/q5.rb +46 -0
  143. data/xquery_use_cases/rdb/q5.xquery +25 -0
  144. data/xquery_use_cases/rdb/q6.out +14 -0
  145. data/xquery_use_cases/rdb/q6.rb +38 -0
  146. data/xquery_use_cases/rdb/q6.xquery +15 -0
  147. data/xquery_use_cases/rdb/q7.out +1 -0
  148. data/xquery_use_cases/rdb/q7.rb +30 -0
  149. data/xquery_use_cases/rdb/q7.xquery +10 -0
  150. data/xquery_use_cases/rdb/q8.out +1 -0
  151. data/xquery_use_cases/rdb/q8.rb +23 -0
  152. data/xquery_use_cases/rdb/q8.xquery +8 -0
  153. data/xquery_use_cases/rdb/q9.out +22 -0
  154. data/xquery_use_cases/rdb/q9.rb +32 -0
  155. data/xquery_use_cases/rdb/q9.xquery +16 -0
  156. data/xquery_use_cases/rdb/users.xml +25 -0
  157. data/xquery_use_cases/seq/README +12 -0
  158. data/xquery_use_cases/seq/q1.out +1 -0
  159. data/xquery_use_cases/seq/q1.rb +25 -0
  160. data/xquery_use_cases/seq/q1.xquery +2 -0
  161. data/xquery_use_cases/seq/q2.out +2 -0
  162. data/xquery_use_cases/seq/q2.rb +25 -0
  163. data/xquery_use_cases/seq/q2.xquery +2 -0
  164. data/xquery_use_cases/seq/q3.out +2 -0
  165. data/xquery_use_cases/seq/q3.rb +26 -0
  166. data/xquery_use_cases/seq/q3.xquery +3 -0
  167. data/xquery_use_cases/seq/q4.out +0 -0
  168. data/xquery_use_cases/seq/q4.rb +27 -0
  169. data/xquery_use_cases/seq/q4.xquery +4 -0
  170. data/xquery_use_cases/seq/q5.out +5 -0
  171. data/xquery_use_cases/seq/q5.rb +29 -0
  172. data/xquery_use_cases/seq/q5.xquery +10 -0
  173. data/xquery_use_cases/seq/report1.xml +40 -0
  174. data/xquery_use_cases/sgml/README +53 -0
  175. data/xquery_use_cases/sgml/q1.out +44 -0
  176. data/xquery_use_cases/sgml/q1.rb +23 -0
  177. data/xquery_use_cases/sgml/q1.xquery +5 -0
  178. data/xquery_use_cases/sgml/q10.out +1 -0
  179. data/xquery_use_cases/sgml/q10.rb +28 -0
  180. data/xquery_use_cases/sgml/q10.xquery +7 -0
  181. data/xquery_use_cases/sgml/q2.out +26 -0
  182. data/xquery_use_cases/sgml/q2.rb +23 -0
  183. data/xquery_use_cases/sgml/q2.xquery +5 -0
  184. data/xquery_use_cases/sgml/q3.out +6 -0
  185. data/xquery_use_cases/sgml/q3.rb +28 -0
  186. data/xquery_use_cases/sgml/q3.xquery +7 -0
  187. data/xquery_use_cases/sgml/q4.out +4 -0
  188. data/xquery_use_cases/sgml/q4.rb +25 -0
  189. data/xquery_use_cases/sgml/q4.xquery +5 -0
  190. data/xquery_use_cases/sgml/q5.out +3 -0
  191. data/xquery_use_cases/sgml/q5.rb +23 -0
  192. data/xquery_use_cases/sgml/q5.xquery +5 -0
  193. data/xquery_use_cases/sgml/q6.out +1 -0
  194. data/xquery_use_cases/sgml/q6.rb +27 -0
  195. data/xquery_use_cases/sgml/q6.xquery +6 -0
  196. data/xquery_use_cases/sgml/q7.out +1 -0
  197. data/xquery_use_cases/sgml/q7.rb +27 -0
  198. data/xquery_use_cases/sgml/q7.xquery +7 -0
  199. data/xquery_use_cases/sgml/q8a.out +34 -0
  200. data/xquery_use_cases/sgml/q8a.rb +27 -0
  201. data/xquery_use_cases/sgml/q8a.xquery +5 -0
  202. data/xquery_use_cases/sgml/q8b.out +26 -0
  203. data/xquery_use_cases/sgml/q8b.rb +32 -0
  204. data/xquery_use_cases/sgml/q8b.xquery +5 -0
  205. data/xquery_use_cases/sgml/q9.out +9 -0
  206. data/xquery_use_cases/sgml/q9.rb +29 -0
  207. data/xquery_use_cases/sgml/q9.xquery +6 -0
  208. data/xquery_use_cases/sgml/sgml.xml +101 -0
  209. data/xquery_use_cases/solution_sizes.rb +48 -0
  210. data/xquery_use_cases/string/README +29 -0
  211. data/xquery_use_cases/string/company-data.xml +20 -0
  212. data/xquery_use_cases/string/q1.out +4 -0
  213. data/xquery_use_cases/string/q1.rb +25 -0
  214. data/xquery_use_cases/string/q1.xquery +1 -0
  215. data/xquery_use_cases/string/q2.out +13 -0
  216. data/xquery_use_cases/string/q2.rb +32 -0
  217. data/xquery_use_cases/string/q2.xquery +23 -0
  218. data/xquery_use_cases/string/q4.out +50 -0
  219. data/xquery_use_cases/string/q4.rb +34 -0
  220. data/xquery_use_cases/string/q4.xquery +14 -0
  221. data/xquery_use_cases/string/q5.out +12 -0
  222. data/xquery_use_cases/string/q5.rb +33 -0
  223. data/xquery_use_cases/string/q5.xquery +8 -0
  224. data/xquery_use_cases/string/string.xml +82 -0
  225. data/xquery_use_cases/test_driver.rb +60 -0
  226. data/xquery_use_cases/tree/README +23 -0
  227. data/xquery_use_cases/tree/book.xml +50 -0
  228. data/xquery_use_cases/tree/q1.out +23 -0
  229. data/xquery_use_cases/tree/q1.rb +31 -0
  230. data/xquery_use_cases/tree/q1.xquery +14 -0
  231. data/xquery_use_cases/tree/q2.out +11 -0
  232. data/xquery_use_cases/tree/q2.rb +27 -0
  233. data/xquery_use_cases/tree/q2.xquery +10 -0
  234. data/xquery_use_cases/tree/q3.out +2 -0
  235. data/xquery_use_cases/tree/q3.rb +26 -0
  236. data/xquery_use_cases/tree/q3.xquery +2 -0
  237. data/xquery_use_cases/tree/q4.out +1 -0
  238. data/xquery_use_cases/tree/q4.rb +23 -0
  239. data/xquery_use_cases/tree/q4.xquery +5 -0
  240. data/xquery_use_cases/tree/q5.out +9 -0
  241. data/xquery_use_cases/tree/q5.rb +30 -0
  242. data/xquery_use_cases/tree/q5.xquery +8 -0
  243. data/xquery_use_cases/tree/q6.out +30 -0
  244. data/xquery_use_cases/tree/q6.rb +35 -0
  245. data/xquery_use_cases/tree/q6.xquery +21 -0
  246. data/xquery_use_cases/xmp/README +41 -0
  247. data/xquery_use_cases/xmp/bib.xml +35 -0
  248. data/xquery_use_cases/xmp/books.xml +15 -0
  249. data/xquery_use_cases/xmp/prices.xml +32 -0
  250. data/xquery_use_cases/xmp/q1.out +8 -0
  251. data/xquery_use_cases/xmp/q1.rb +29 -0
  252. data/xquery_use_cases/xmp/q1.xquery +10 -0
  253. data/xquery_use_cases/xmp/q10.out +11 -0
  254. data/xquery_use_cases/xmp/q10.rb +36 -0
  255. data/xquery_use_cases/xmp/q10.xquery +11 -0
  256. data/xquery_use_cases/xmp/q11.out +35 -0
  257. data/xquery_use_cases/xmp/q11.rb +37 -0
  258. data/xquery_use_cases/xmp/q11.xquery +18 -0
  259. data/xquery_use_cases/xmp/q12.out +6 -0
  260. data/xquery_use_cases/xmp/q12.rb +35 -0
  261. data/xquery_use_cases/xmp/q12.xquery +20 -0
  262. data/xquery_use_cases/xmp/q2.out +37 -0
  263. data/xquery_use_cases/xmp/q2.rb +30 -0
  264. data/xquery_use_cases/xmp/q2.xquery +12 -0
  265. data/xquery_use_cases/xmp/q3.out +34 -0
  266. data/xquery_use_cases/xmp/q3.rb +27 -0
  267. data/xquery_use_cases/xmp/q3.xquery +10 -0
  268. data/xquery_use_cases/xmp/q4.out +31 -0
  269. data/xquery_use_cases/xmp/q4.rb +44 -0
  270. data/xquery_use_cases/xmp/q4.xquery +21 -0
  271. data/xquery_use_cases/xmp/q5.out +17 -0
  272. data/xquery_use_cases/xmp/q5.rb +38 -0
  273. data/xquery_use_cases/xmp/q5.xquery +13 -0
  274. data/xquery_use_cases/xmp/q6.out +28 -0
  275. data/xquery_use_cases/xmp/q6.rb +33 -0
  276. data/xquery_use_cases/xmp/q6.xquery +19 -0
  277. data/xquery_use_cases/xmp/q7.out +8 -0
  278. data/xquery_use_cases/xmp/q7.rb +30 -0
  279. data/xquery_use_cases/xmp/q7.xquery +12 -0
  280. data/xquery_use_cases/xmp/q8.out +7 -0
  281. data/xquery_use_cases/xmp/q8.rb +29 -0
  282. data/xquery_use_cases/xmp/q8.xquery +9 -0
  283. data/xquery_use_cases/xmp/q9.out +4 -0
  284. data/xquery_use_cases/xmp/q9.rb +29 -0
  285. data/xquery_use_cases/xmp/q9.xquery +7 -0
  286. data/xquery_use_cases/xmp/reviews.xml +24 -0
  287. metadata +342 -0
@@ -0,0 +1,855 @@
1
+ #!/usr/bin/env ruby
2
+ #Copyright (c) 2006-2007 Tomasz Wegrzanowski <Tomasz.Wegrzanowski@gmail.com>
3
+ #
4
+ #Permission is hereby granted, free of charge, to any person obtaining a
5
+ #copy of this software and associated documentation files (the "Software"),
6
+ #to deal in the Software without restriction, including without limitation
7
+ #the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
+ #and/or sell copies of the Software, and to permit persons to whom the
9
+ #Software is furnished to do so, subject to the following conditions:
10
+ #
11
+ #The above copyright notice and this permission notice shall be included in
12
+ #all copies or substantial portions of the Software.
13
+ #
14
+ #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
+ #THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
+ #OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
+ #ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
+ #DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'helper'
23
+
24
+ # For tests
25
+ require 'stringio'
26
+
27
+ class XML_Tests < Test::Unit::TestCase
28
+ # Test whether XML.new constructors work (without monadic case)
29
+ def test_constructors
30
+ br = XML.new(:br)
31
+ h3 = XML.new(:h3, "Hello")
32
+ a = XML.new(:a, {:href => "http://www.google.com/"}, "Google")
33
+ ul = XML.new(:ul, XML.new(:li, "Hello"), XML.new(:li, "world"))
34
+
35
+ assert_equal("<br/>", br.to_s, "Constructors should work")
36
+ assert_equal("<h3>Hello</h3>", h3.to_s, "Constructors should work")
37
+ assert_equal("<a href='http://www.google.com/'>Google</a>", a.to_s, "Constructors should work")
38
+ assert_equal("<ul><li>Hello</li><li>world</li></ul>", ul.to_s, "Constructors should work")
39
+ end
40
+
41
+ # Test character escaping on output, in text and in attribute values
42
+ def test_escapes
43
+ p = XML.new(:p, "< > &")
44
+ foo = XML.new(:foo, {:bar=>"< > ' \" &"})
45
+
46
+ assert_equal("<p>&lt; &gt; &amp;</p>", p.to_s, "Character escaping should work")
47
+ assert_equal("<foo bar='&lt; &gt; &apos; &quot; &amp;'/>", foo.to_s, "Character escaping in attributes should work")
48
+ end
49
+
50
+ # Test #sort_by and #children_sort_by
51
+ def test_sort_by
52
+ doc = XML.parse("<foo><bar id='5'/>a<bar id='3'/>c<bar id='4'/>b<bar id='1'/></foo>")
53
+
54
+ doc_by_id = doc.sort_by{|c| c[:id]}
55
+ assert_equal("<foo><bar id='1'/><bar id='3'/><bar id='4'/><bar id='5'/></foo>", doc_by_id.to_s)
56
+
57
+ doc_all_by_id = doc.children_sort_by{|c| if c.is_a? XML then [0, c[:id]] else [1, c] end}
58
+ assert_equal("<foo><bar id='1'/><bar id='3'/><bar id='4'/><bar id='5'/>abc</foo>", doc_all_by_id.to_s)
59
+ end
60
+
61
+ # Test XML#[] and XML#[]= for attribute access
62
+ def test_attr
63
+ foo = XML.new(:foo, {:x => "1"})
64
+ assert_equal("1", foo[:x], "Attribute reading should work")
65
+ foo[:x] = "2"
66
+ foo[:y] = "3"
67
+ assert_equal("2", foo[:x], "Attribute writing should work")
68
+ assert_equal("3", foo[:y], "Attribute writing should work")
69
+ end
70
+
71
+ # Test XML#<< method for adding children
72
+ def test_add
73
+ a = XML.new(:p, "Hello")
74
+ a << ", "
75
+ a << "world!"
76
+ assert_equal("<p>Hello, world!</p>", a.to_s, "XML#<< should work")
77
+
78
+ b = XML.new(:foo)
79
+ b << XML.new(:bar)
80
+ assert_equal("<foo><bar/></foo>", b.to_s, "XML#<< should work")
81
+ end
82
+
83
+ # Test XML#each method for iterating over children
84
+ def test_each
85
+ a = XML.new(:p, "Hello", ", ", "world", XML.new(:br))
86
+ b = ""
87
+ a.each{|c| b += c.to_s}
88
+ assert_equal("Hello, world<br/>", b, "XML#each should work")
89
+ end
90
+
91
+ # Test XML#map method
92
+ def test_map
93
+ a = XML.new(:body, XML.new(:h3, "One"), "Hello", XML.new(:h3, "Two"))
94
+ b = a.map{|c|
95
+ if c.is_a? XML and c.name == :h3
96
+ XML.new(:h2, c.attrs, *c.contents)
97
+ else
98
+ c
99
+ end
100
+ }
101
+ assert_equal("<body><h3>One</h3>Hello<h3>Two</h3></body>", a.to_s, "XML#map should not modify the argument")
102
+ assert_equal("<body><h2>One</h2>Hello<h2>Two</h2></body>", b.to_s, "XML#map should work")
103
+
104
+ d = a.map(:h3) {|c|
105
+ XML.new(:h2, c.attrs, *c.contents)
106
+ }
107
+ assert_equal("<body><h2>One</h2>Hello<h2>Two</h2></body>", d.to_s, "XML#map should accept selectors")
108
+ end
109
+
110
+ # Test XML#==
111
+ def test_eqeq
112
+ a = XML.new(:foo)
113
+ b = XML.new(:foo)
114
+ c = XML.new(:bar)
115
+ assert(a==a, "XML#== should work")
116
+ assert(a==b, "XML#== should work")
117
+ assert(a!=c, "XML#== should work")
118
+
119
+ d = XML.new(:foo, {:bar => "1"})
120
+ e = XML.new(:foo, {:bar => "1"})
121
+ f = XML.new(:foo, {:bar => "2"})
122
+ assert(d==d, "XML#== should work")
123
+ assert(d==e, "XML#== should work")
124
+ assert(d!=f, "XML#== should work")
125
+
126
+ a = XML.new(:foo, "Hello, world!")
127
+ b = XML.new(:foo, "Hello, world!")
128
+ c = XML.new(:foo, "Hello", ", world!")
129
+ d = XML.new(:foo, "Hello")
130
+ e = XML.new(:foo, "Hello", "")
131
+ assert(a==a, "XML#== should work")
132
+ assert(a==b, "XML#== should work")
133
+ assert(a==c, "XML#== should work")
134
+ assert(a!=d, "XML#== should work")
135
+ assert(d==e, "Empty children should not affect XML#==")
136
+
137
+ # Highly pathological case
138
+ a = XML.new(:foo, "ab", "cde", "", "fg", "hijk", "", "")
139
+ b = XML.new(:foo, "", "abc", "d", "efg", "h", "ijk")
140
+ assert(a==b, "XML#== should work with differently split Strings too")
141
+
142
+ # String vs XML
143
+ a = XML.new(:foo, "Hello")
144
+ b = XML.new(:foo) {foo!}
145
+ c = XML.new(:foo) {bar!}
146
+ assert(a!=b, "XML#== should work with children of different types")
147
+ assert(b!=c, "XML#== should work recursively")
148
+
149
+ a = XML.new(:foo) {foo!; bar!}
150
+ b = XML.new(:foo) {foo!; foo!}
151
+ assert(a!=b, "XML#== should work recursively")
152
+ end
153
+
154
+ # Test dup-with-block method
155
+ def test_dup
156
+ a = XML.new(:foo, {:a => "1"}, "Hello")
157
+ b = a.dup{ @name = :bar }
158
+ c = a.dup{ self[:a] = "2" }
159
+ d = a.dup{ self << ", world!" }
160
+
161
+ assert_equal("<foo a='1'>Hello</foo>", a.to_s, "XML#dup{} should not modify its argument")
162
+ assert_equal("<bar a='1'>Hello</bar>", b.to_s, "XML#dup{} should work")
163
+ assert_equal("<foo a='2'>Hello</foo>", c.to_s, "XML#dup{} should work")
164
+ assert_equal("<foo a='1'>Hello, world!</foo>", d.to_s, "XML#dup{} should work")
165
+
166
+ # Deep copy test
167
+ a = XML.new(:h3, "Hello")
168
+ b = XML.new(:foo, XML.new(:bar, a))
169
+ c = b.dup
170
+ a << ", world!"
171
+
172
+ assert_equal("<foo><bar><h3>Hello, world!</h3></bar></foo>", b.to_s, "XML#dup should make a deep copy")
173
+ assert_equal("<foo><bar><h3>Hello</h3></bar></foo>", c.to_s, "XML#dup should make a deep copy")
174
+ end
175
+
176
+ # Test XML#normalize! method
177
+ def test_normalize
178
+ a = XML.new(:foo, "He", "", "llo")
179
+ b = XML.new(:foo, "")
180
+ c = XML.new(:foo, "", XML.new(:bar, "1"), "", XML.new(:bar, "2", ""), "X", XML.new(:bar, "", "3"), "")
181
+
182
+ a.normalize!
183
+ b.normalize!
184
+ c.normalize!
185
+
186
+ assert_equal(["Hello"], a.contents, "XML#normalize! should work")
187
+ assert_equal([], b.contents, "XML#normalize! should work")
188
+ assert_equal([XML.new(:bar, "1"), XML.new(:bar, "2"), "X", XML.new(:bar, "3")], c.contents, "XML#normalize! should work")
189
+ end
190
+
191
+ # Test the "monadic" interface, that is constructors
192
+ # with instance_eval'd blocks passed to them:
193
+ # XML.new(:foo) { bar! } # -> <foo><bar/></foo>
194
+ def test_monadic
195
+ a = XML.new(:foo) { bar!; xml!(:xxx) }
196
+ b = xml(:div) {
197
+ ul! {
198
+ li!(XML.a("Hello"))
199
+ }
200
+ }
201
+ assert_equal("<foo><bar/><xxx/></foo>", a.to_s, "Monadic interface should work")
202
+ assert_equal("<div><ul><li><a>Hello</a></li></ul></div>", b.to_s, "Monadic interface should work")
203
+ end
204
+
205
+ # Test if parsing and printing gives the right results
206
+ # We test mostly round-trip
207
+ def test_parse
208
+ a = "<foo/>"
209
+ b = "<foo a='1'/>"
210
+ c = "<foo>Hello</foo>"
211
+ d = "<foo a='1'><bar b='2'>Hello</bar><bar b='3'>world</bar></foo>"
212
+ e = "<foo>&gt; &lt; &amp;</foo>"
213
+ f = "<foo a='b&amp;c'/>"
214
+
215
+ assert_equal(a, XML.parse(a).to_s, "XML.parse(x).to_s should equal x for normalized x")
216
+ assert_equal(b, XML.parse(b).to_s, "XML.parse(x).to_s should equal x for normalized x")
217
+ assert_equal(c, XML.parse(c).to_s, "XML.parse(x).to_s should equal x for normalized x")
218
+ assert_equal(d, XML.parse(d).to_s, "XML.parse(x).to_s should equal x for normalized x")
219
+ assert_equal(e, XML.parse(e).to_s, "XML.parse(x).to_s should equal x for normalized x")
220
+ assert_equal(f, XML.parse(f).to_s, "XML.parse(x).to_s should equal x for normalized x")
221
+ end
222
+
223
+ # Test parsing &-entities
224
+ def test_parse_extra_escapes
225
+ a = "<foo>&quot; &apos;</foo>"
226
+ a_out = "<foo>\" '</foo>"
227
+
228
+ assert_equal(a_out, XML.parse(a).to_s, "XML.parse(x).to_s should normalize entities in x")
229
+ end
230
+
231
+ # Test handling extra cruft
232
+ # Some things are best ignored or normalized
233
+ def test_parse_extra_cdata
234
+ a = "<foo><![CDATA[<greeting>Hello, world!</greeting>]]></foo>"
235
+ a_out = "<foo>&lt;greeting&gt;Hello, world!&lt;/greeting&gt;</foo>"
236
+ assert_equal(a_out, XML.parse(a).to_s, "XML.parse(x).to_s should equal normalized x")
237
+ end
238
+
239
+ # Test handling (=ignoring) XML declarations
240
+ def test_parse_extra_qxml
241
+ b = "<?xml version=\"1.0\"?><greeting>Hello, world!</greeting>"
242
+ b_out = "<greeting>Hello, world!</greeting>"
243
+ assert_equal(b_out, XML.parse(b).to_s, "XML.parse(x).to_s should equal normalized x")
244
+ end
245
+
246
+ # Test handling (=ignoring) DTDs
247
+ def test_parse_extra_dtd
248
+ c = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]><greeting>Hello, world!</greeting>"
249
+ c_out = "<greeting>Hello, world!</greeting>"
250
+ assert_equal(c_out, XML.parse(c).to_s, "XML.parse(x).to_s should equal normalized x")
251
+ end
252
+
253
+ # Test handling (=ignoring) DTDs
254
+ def test_parse_extra_comment
255
+ c = "<!-- this is a comment --><greeting>Hello,<!-- another comment --> world!</greeting>"
256
+ c_out = "<greeting>Hello, world!</greeting>"
257
+ assert_equal(c_out, XML.parse(c).to_s, "XML.parse(x).to_s should equal normalized x")
258
+ end
259
+
260
+ # Test reading from a file
261
+ def test_parse_file
262
+ a = File.open("test.xml").xml_parse
263
+ b = XML.from_file("test.xml")
264
+ c = XML.from_url("file:test.xml")
265
+ d = XML.from_url("string:<foo><bar></bar></foo>")
266
+ e = XML.parse("<foo><bar></bar></foo>")
267
+ f = "<foo><bar></bar></foo>".xml_parse
268
+ g = XML.foo { bar! }
269
+
270
+ assert_equal(g.to_s, a.to_s, "File#xml_parse should work")
271
+ assert_equal(g.to_s, b.to_s, "XML.from_file should work")
272
+ assert_equal(g.to_s, c.to_s, "XML.from_url(\"file:...\") should work")
273
+ assert_equal(g.to_s, d.to_s, "XML.from_url(\"string:...\") should work")
274
+ assert_equal(g.to_s, e.to_s, "XML.parse should work")
275
+ assert_equal(g.to_s, f.to_s, "String#xml_parse should work")
276
+ end
277
+
278
+ # Test XML#children and Array#children
279
+ def test_chilrden
280
+ a = XML.bar({:x=>"1"})
281
+ b = XML.bar({:x=>"3"})
282
+ c = XML.bar({:x=>"2"}, b)
283
+ d = XML.foo(a,c)
284
+ e = d.children(:bar)
285
+ f = e.children(:bar)
286
+ assert_equal([a,c], e, "XML#children(tag) should return tag-tagged children")
287
+ assert_equal([b], f, "Array#children(tag) should return tag-tagged children of its elements")
288
+ end
289
+
290
+ # Test XML#descendants and Array#descendants
291
+ def test_descendants
292
+ a = XML.bar({:x=>"1"})
293
+ b = XML.bar({:x=>"3"})
294
+ c = XML.bar({:x=>"2"}, b)
295
+ d = XML.foo(a,c)
296
+ e = d.descendants(:bar)
297
+ f = e.descendants(:bar)
298
+ assert_equal([a,c,b], e, "XML#descendants(tag) should return tag-tagged descendants")
299
+ assert_equal([b], f, "Array#descendants(tag) should return tag-tagged descendants of its elements")
300
+ end
301
+
302
+ # Test XML#exec! monadic interface
303
+ def test_exec
304
+ a = XML.foo
305
+ a.exec! {
306
+ bar! { text! "Hello" }
307
+ text! "world"
308
+ }
309
+ assert_equal("<foo><bar>Hello</bar>world</foo>", a.to_s, "XML#exec! should work")
310
+ end
311
+
312
+ # Test XML#child
313
+ def test_child
314
+ a = XML.parse("<foo></foo>")
315
+ b = XML.parse("<foo><bar a='1'/></foo>")
316
+ c = XML.parse("<foo><bar a='1'/><bar a='2'/></foo>")
317
+
318
+ assert_equal(nil, a.child(:bar), "XML#child should return nil if there are no matching children")
319
+ assert_equal("<bar a='1'/>", b.child(:bar).to_s, "XML#child should work")
320
+ assert_equal("<bar a='1'/>", c.child(:bar).to_s, "XML#child should return first child if there are many")
321
+ assert_equal("<bar a='2'/>", c.child({:a => '2'}).to_s, "XML#child should support patterns")
322
+ end
323
+
324
+ # Test XML#descendant
325
+ def test_descendant
326
+ a = XML.parse("<foo></foo>")
327
+ b = XML.parse("<foo><bar a='1'/></foo>")
328
+ c = XML.parse("<foo><bar a='1'/><bar a='2'/></foo>")
329
+ d = XML.parse("<foo><bar a='1'><bar a='2'/></bar><bar a='3'/></foo>")
330
+ e = XML.parse("<foo><foo><bar a='1'/></foo><bar a='2'/></foo>")
331
+
332
+ assert_equal(nil, a.descendant(:bar), "XML#descendant should return nil if there are no matching descendants")
333
+ assert_equal("<bar a='1'/>", b.descendant(:bar).to_s, "XML#descendant should work")
334
+ assert_equal("<bar a='1'/>", c.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
335
+ assert_equal("<bar a='1'><bar a='2'/></bar>", d.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
336
+ assert_equal("<bar a='1'/>", e.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
337
+ assert_equal("<bar a='2'/>", c.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
338
+ assert_equal("<bar a='2'/>", d.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
339
+ assert_equal("<bar a='2'/>", e.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
340
+ end
341
+
342
+ # Test XML#text
343
+ def test_text
344
+ a = XML.parse("<foo>Hello</foo>")
345
+ b = XML.parse("<foo></foo>")
346
+ c = XML.parse("<foo><bar>Hello</bar></foo>")
347
+ d = XML.parse("<foo>He<bar>llo</bar></foo>")
348
+
349
+ assert_equal("Hello", a.text, "XML#text should work")
350
+ assert_equal("", b.text, "XML#text should work")
351
+ assert_equal("Hello", c.text, "XML#text should work")
352
+ assert_equal("Hello", d.text, "XML#text should work")
353
+ end
354
+
355
+ # Test XML#renormalize and XML#renormalize_sequence
356
+ def test_renormalize
357
+ a = "<foo></foo>"
358
+ b = "<foo></foo><bar></bar>"
359
+
360
+ assert_equal("<foo/>", XML.renormalize(a), "XML#renormalize should work")
361
+ assert_equal("<foo/>", XML.renormalize_sequence(a), "XML#renormalize_sequence should work")
362
+ assert_equal("<foo/><bar/>", XML.renormalize_sequence(b), "XML#renormalize_sequence should work")
363
+ end
364
+
365
+ # Test XML#range
366
+ def test_range
367
+ a = XML.parse "<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>"
368
+ b = a.children(:bar)
369
+
370
+ # Non-recursive case
371
+ ar_n_n = a.range(nil, nil)
372
+ ar_0_n = a.range(b[0], nil)
373
+ ar_1_n = a.range(b[1], nil)
374
+ ar_4_n = a.range(b[4], nil)
375
+ ar_n_4 = a.range(nil, b[4])
376
+ ar_n_3 = a.range(nil, b[3])
377
+ ar_n_0 = a.range(nil, b[0])
378
+
379
+ assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_n_n.to_s, "XML#range should work")
380
+ assert_equal("<foo><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_0_n.to_s, "XML#range should work")
381
+ assert_equal("<foo><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_1_n.to_s, "XML#range should work")
382
+ assert_equal("<foo/>", ar_4_n.to_s, "XML#range should work")
383
+ assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/></foo>", ar_n_4.to_s, "XML#range should work")
384
+ assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/></foo>", ar_n_3.to_s, "XML#range should work")
385
+ assert_equal("<foo/>", ar_n_0.to_s, "XML#range should work")
386
+
387
+ a = XML.parse "<a>
388
+ <b i='0'><c i='0'/><c i='1'/><c i='2'/></b>
389
+ <b i='1'><c i='3'/><c i='4'/><c i='5'/></b>
390
+ <b i='2'><c i='6'/><c i='7'/><c i='8'/></b>
391
+ </a>"
392
+ c = a.descendants(:c)
393
+
394
+ c.each_with_index{|ci,i|
395
+ c.each_with_index{|cj,j|
396
+ next unless i < j
397
+ ar = a.range(ci,cj)
398
+ cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
399
+ assert_equal(((i+1)...j).to_a, cs_present, "XML#range(c#{i}, c#{j}) should contain cs between #{i} and #{j}, exclusive, instead got: #{ar}")
400
+ }
401
+ ar = a.range(ci,nil)
402
+ cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
403
+ assert_equal(((i+1)..8).to_a, cs_present, "XML#range(c#{i}, nil) should contain cs from #{i+1} to 8, instead got: #{ar}")
404
+
405
+ ar = a.range(nil,ci)
406
+ cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
407
+ assert_equal((0...i).to_a, cs_present, "XML#range(nil, c#{i}) should contain cs from 0 to #{i-1}, instead got: #{ar}")
408
+ }
409
+ end
410
+
411
+ # Test XML#subsequence
412
+ def test_subsequence
413
+ a = XML.parse "<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>"
414
+ b = a.children(:bar)
415
+
416
+ # Non-recursive case
417
+ ar_n_n = a.subsequence(nil, nil)
418
+ ar_0_n = a.subsequence(b[0], nil)
419
+ ar_1_n = a.subsequence(b[1], nil)
420
+ ar_4_n = a.subsequence(b[4], nil)
421
+ ar_n_4 = a.subsequence(nil, b[4])
422
+ ar_n_3 = a.subsequence(nil, b[3])
423
+ ar_n_0 = a.subsequence(nil, b[0])
424
+
425
+ assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_n_n.to_s, "XML#subsequence should work")
426
+ assert_equal("<bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/>", ar_0_n.to_s, "XML#subsequence should work")
427
+ assert_equal("<bar i='2'/><bar i='3'/><bar i='4'/>", ar_1_n.to_s, "XML#subsequence should work")
428
+ assert_equal("", ar_4_n.to_s, "XML#subsequence should work")
429
+ assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/></foo>", ar_n_4.to_s, "XML#subsequence should work")
430
+ assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/></foo>", ar_n_3.to_s, "XML#subsequence should work")
431
+ assert_equal("<foo/>", ar_n_0.to_s, "XML#subsequence should work")
432
+
433
+ a = XML.parse "<a>
434
+ <b j='0'><c i='0'/><c i='1'/><c i='2'/></b>
435
+ <b j='1'><c i='3'/><c i='4'/><c i='5'/></b>
436
+ <b j='2'><c i='6'/><c i='7'/><c i='8'/></b>
437
+ </a>"
438
+ c = a.descendants(:c)
439
+
440
+ # (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}
441
+ # instead of ar.descendants(:c) because
442
+ # we might have returned [<c i='?'/>] as a result,
443
+ # and then it's not a descendant of the result then.
444
+ # This is ugly, and it should be fixed somewhere in magic/xml
445
+ c.each_with_index{|ci,i|
446
+ c.each_with_index{|cj,j|
447
+ next unless i < j
448
+ ar = a.subsequence(ci,cj)
449
+ cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
450
+ assert_equal(((i+1)...j).to_a, cs_present, "XML#subsequence(c#{i}, c#{j}) should contain cs between #{i} and #{j}, exclusive, instead got: #{ar}")
451
+ }
452
+ ar = a.subsequence(ci,nil)
453
+ cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
454
+ assert_equal(((i+1)..8).to_a, cs_present, "XML#subsequence(c#{i}, nil) should contain cs from #{i+1} to 8, instead got: #{ar}")
455
+
456
+ ar = a.subsequence(nil,ci)
457
+ cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
458
+ assert_equal((0...i).to_a, cs_present, "XML#subsequence(nil, c#{i}) should contain cs from 0 to #{i-1}, instead got: #{ar}")
459
+ }
460
+ end
461
+
462
+ # Test xml! at top level
463
+ def test_xml_bang
464
+ real_stdout = $stdout
465
+ $stdout = StringIO.new
466
+ xml!(:foo)
467
+ assert_equal("<foo/>", $stdout.string, "xml! should work")
468
+
469
+ $stdout = StringIO.new
470
+ XML.bar!
471
+ assert_equal("<bar/>", $stdout.string, "XML#foo! should work")
472
+ $stdout = real_stdout
473
+ end
474
+
475
+ # Methods XML#foo! are all catched,
476
+ # but how about other methods ?
477
+ def test_real_method_missing
478
+ foo = XML.new(:foo)
479
+ exception_raised = false
480
+ begin
481
+ foo.bar()
482
+ rescue NoMethodError
483
+ exception_raised = true
484
+ end
485
+ # FIXME: There are other assertions than assert_equal ;-)
486
+ assert_equal(true, exception_raised, "XML#bar should raise NoMethodError")
487
+ end
488
+
489
+ # Test XML#parse_as_twigs interface
490
+ def test_parse_as_twigs
491
+ stream = "<foo><p><ul><li>1</li><li>2</li><li>3</li></ul></p><p><br/></p><p/><p><bar/></p></foo>"
492
+ i = 0
493
+ results = []
494
+ XML.parse_as_twigs(stream) {|n|
495
+ n.complete! if i == 1 or i == 3
496
+ results << n
497
+ i += 1
498
+ }
499
+ assert_equal("<foo/>", results[0].to_s, "XML.parse_as_twigs should work")
500
+ assert_equal("<p><ul><li>1</li><li>2</li><li>3</li></ul></p>", results[1].to_s, "XML.parse_as_twigs should work")
501
+ assert_equal("<p/>", results[2].to_s, "XML.parse_as_twigs should work")
502
+ assert_equal("<br/>", results[3].to_s, "XML.parse_as_twigs should work")
503
+ assert_equal("<p/>", results[4].to_s, "XML.parse_as_twigs should work")
504
+ assert_equal("<p/>", results[5].to_s, "XML.parse_as_twigs should work")
505
+ assert_equal("<bar/>", results[6].to_s, "XML.parse_as_twigs should work")
506
+ assert_equal(7, results.size, "XML.parse_as_twigs should work")
507
+ end
508
+
509
+ # Test XML#inspect
510
+ def test_inpsect
511
+ a = xml(:a, xml(:b, xml(:c)))
512
+ d = xml(:d)
513
+
514
+ assert_equal("<a>...</a>", a.inspect, "XML#inspect should work")
515
+ assert_equal("<a>...</a>", a.inspect(0), "XML#inspect(levels) should work")
516
+ assert_equal("<a><b>...</b></a>", a.inspect(1), "XML#inspect(levels) should work")
517
+ assert_equal("<a><b><c/></b></a>", a.inspect(2), "XML#inspect(levels) should work")
518
+ assert_equal("<a><b><c/></b></a>", a.inspect(3), "XML#inspect(levels) should work")
519
+ assert_equal("<d/>", d.inspect, "XML#inspect should work")
520
+ assert_equal("<d/>", d.inspect(0), "XML#inspect should work")
521
+ assert_equal("<d/>", d.inspect(1), "XML#inspect should work")
522
+ end
523
+
524
+ # Test XML#[:@foo] pseudoattributes
525
+ def test_pseudoattributes_read
526
+ # Ignore the second <x>...</x>
527
+ a = XML.parse("<foo x='10'><x>20</x><y>30</y><x>40</x></foo>")
528
+
529
+ assert_equal("10", a[:x], "XML#[] real attributes should work")
530
+ assert_nil(a[:y], "XML#[] real attributes should work")
531
+ assert_nil(a[:z], "XML#[] real attributes should work")
532
+ assert_equal("20", a[:@x], "XML#[] pseudoattributes should work")
533
+ assert_equal("30", a[:@y], "XML#[] pseudoattributes should work")
534
+ assert_nil(a[:@z], "XML#[] pseudoattributes should work")
535
+ end
536
+
537
+ # Test XML#[:@foo] pseudoattributes
538
+ def test_pseudoattributes_write
539
+ # Ignore the second <x>...</x>
540
+ a = XML.parse("<foo x='10'><x>20</x><y>30</y><x>40</x></foo>")
541
+
542
+ a[:x] = 100
543
+ a[:y] = 200
544
+ a[:z] = 300
545
+ a[:@x] = 1000
546
+ a[:@y] = 2000
547
+ a[:@z] = 3000
548
+
549
+ assert_equal("<foo x='100' y='200' z='300'><x>1000</x><y>2000</y><x>40</x><z>3000</z></foo>", a.to_s, "XML#[]= pseudoattributes should work")
550
+ end
551
+
552
+ # Test entity unescaping
553
+ def test_entities
554
+ a = XML.parse("<foo>&#xA5;&#xFC;&#x2020;</foo>")
555
+ b = XML.parse("<foo>&#165;&#252;&#8224;</foo>")
556
+ c = XML.parse("<foo>&yen;&uuml;&dagger;</foo>")
557
+ d = ""
558
+
559
+ assert_equal(b.text, a.text, "Entity unescaping on XML#Parse should work")
560
+ assert_equal(c.text, a.text, "Entity unescaping on XML#Parse should work")
561
+
562
+ assert_equal(b.to_s, a.to_s, "Entity escaping on XML#to_s should work")
563
+ assert_equal(c.to_s, a.to_s, "Entity escaping on XML#to_s should work")
564
+
565
+ # The escapes assume \XXX are byte escapes and the encoding is UTF-8
566
+ assert_equal("\302\245\303\274\342\200\240", a.text, "Entity unescaping on XML#Parse should work")
567
+ assert_equal("<foo>\302\245\303\274\342\200\240</foo>", a.to_s, "Entity escaping on XML#to_s should work")
568
+ end
569
+
570
+ # Test patterns support
571
+ def test_patterns
572
+ a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl>!</excl></foo>"
573
+ a.normalize!
574
+
575
+ blue = []
576
+ nocolor = []
577
+ bar = []
578
+ #hello = []
579
+
580
+ a.descendants {|d|
581
+ case d
582
+ when :bar
583
+ bar << d
584
+ end
585
+
586
+ case d
587
+ when {:color => 'blue'}
588
+ blue << d
589
+ end
590
+
591
+ case d
592
+ when {:color => nil}
593
+ nocolor << d
594
+ end
595
+
596
+ #case d
597
+ #when /Hello/
598
+ # hello << d
599
+ #end
600
+ }
601
+
602
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
603
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue, "Pattern matching should work")
604
+ assert_equal([XML.parse("<excl>!</excl>")], nocolor, "Pattern matching should work")
605
+ # Commented out, as it requires overloading Regexp#=~ and therefore Binding.of_caller
606
+ #assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
607
+ end
608
+
609
+ # Test pattern support in #descendants (works the same way in #children)
610
+ def test_patterns_2
611
+ a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl color='blue'>!</excl></foo>"
612
+ a.normalize!
613
+
614
+ bar = a.descendants(:bar)
615
+ blue = a.descendants({:color=>'blue'})
616
+ blue_bar = a.descendants(all(:bar, {:color=>'blue'}))
617
+ #hello = a.descendants(/Hello/)
618
+ xml = a.descendants(XML)
619
+ string = a.descendants(String)
620
+
621
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
622
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<excl color='blue'>!</excl>")], blue, "Pattern matching should work")
623
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue_bar, "Pattern matching should work")
624
+ # Commented out, as it requires overloading Regexp#=~ and therefore Binding.of_caller
625
+ #assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
626
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>"), XML.parse("<excl color='blue'>!</excl>")], xml, "Pattern matching should work")
627
+ assert_equal(['Hello', ', ', 'world', '!'], string, "Pattern matching should work")
628
+ end
629
+
630
+ # Test patterns =~ support
631
+ def test_patterns_3
632
+ a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl>!</excl></foo>"
633
+ a.normalize!
634
+
635
+ blue = []
636
+ nocolor = []
637
+ bar = []
638
+ hello = []
639
+
640
+ a.descendants {|d|
641
+ if d =~ :bar
642
+ bar << d
643
+ end
644
+
645
+ if d =~ {:color => 'blue'}
646
+ blue << d
647
+ end
648
+
649
+ if d =~ {:color => nil}
650
+ nocolor << d
651
+ end
652
+
653
+ if d =~ /Hello/
654
+ hello << d
655
+ end
656
+ }
657
+
658
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
659
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue, "Pattern matching should work")
660
+ assert_equal([XML.parse("<excl>!</excl>")], nocolor, "Pattern matching should work")
661
+ assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
662
+ end
663
+
664
+ def test_patterns_any_all
665
+ a = XML.parse "<foo>
666
+ <bar color='blue' size='big'>1</bar>
667
+ <bar color='blue'>2</bar>
668
+ <bar color='blue' size='normal'>3</bar>
669
+ <bar color='red' size='big'>4</bar>
670
+ <bar color='red'>5</bar>
671
+ <bar color='red' size='normal'>6</bar>
672
+ </foo>"
673
+
674
+ p = all({:color => 'red'}, any({:size => nil}, {:size => 'normal'}))
675
+ # Select childern which color red and size either normal or not specified
676
+ b = a.children(p)
677
+ c = a.find_all{|x| x =~ p }
678
+ d = a.find_all{|x| p === x }
679
+
680
+ assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", b.to_s, "Pattern matching with any/all should work")
681
+ assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", c.to_s, "Pattern matching with any/all should work")
682
+ assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", d.to_s, "Pattern matching with any/all should work")
683
+ end
684
+
685
+ # Test parse option :ignore_pretty_printing
686
+ def test_remove_pretty_printing
687
+ a = "<foo><bar>100</bar><bar>200</bar></foo>"
688
+ b = "<foo>
689
+ <bar>
690
+ 100
691
+ </bar>
692
+ <bar>
693
+ 200
694
+ </bar>
695
+ </foo>"
696
+ c = XML.parse(a)
697
+ d = XML.parse(b)
698
+ e = XML.parse(b)
699
+ e.remove_pretty_printing!
700
+
701
+ assert_not_equal(c.to_s, d.to_s, "XML#parse should not ignore pretty printing by default")
702
+ assert_equal(c.to_s, e.to_s, "XML#remove_pretty_printing! should work")
703
+
704
+ f = XML.parse("<foo> <bar>Hello world</bar> </foo>")
705
+ f.remove_pretty_printing!
706
+ g = XML.parse("<foo><bar>Hello world</bar></foo>")
707
+ assert_equal(f.to_s, g.to_s, "XML#remove_pretty_printing! should work")
708
+ end
709
+
710
+ # Test remove_pretty_printing! with exception list
711
+ def test_remove_pretty_printing_conditional
712
+ a = "<foo>
713
+ <pre>
714
+ <a> 100 </a>
715
+ </pre>
716
+ <xyzzy>
717
+ <a> 200 </a>
718
+ </xyzzy>
719
+ </foo>"
720
+ b = "<foo><pre>
721
+ <a> 100 </a>
722
+ </pre><xyzzy><a>200</a></xyzzy></foo>"
723
+
724
+ ax = XML.parse(a)
725
+ bx = XML.parse(b)
726
+
727
+ ax.remove_pretty_printing!([:pre])
728
+
729
+ assert_equal(bx.to_s, ax.to_s, "XML#remove_pretty_printing!(exceptions) should work")
730
+ end
731
+
732
+ # Test extra arguments to XML#parse - :comments and :pi
733
+ def test_parsing_extras
734
+ a = "<foo><?xml-stylesheet href='http://www.blogger.com/styles/atom.css' type='text/css'?></foo>"
735
+ b = "<foo><!-- This is a comment --></foo>"
736
+
737
+ ax = XML.parse(a)
738
+ bx = XML.parse(b)
739
+
740
+ assert_equal("<foo/>", ax.to_s, "XML#parse should drop PI by default")
741
+ assert_equal("<foo/>", bx.to_s, "XML#parse should drop comments by default")
742
+
743
+ ay = XML.parse(a, :comments => true, :pi => true)
744
+ by = XML.parse(b, :comments => true, :pi => true)
745
+
746
+ assert_equal(a, ay.to_s, "XML#parse(str, :pi=>true) should include PI")
747
+ assert_equal(b, by.to_s, "XML#parse(str, :comments=>true) should include comments")
748
+ end
749
+
750
+ # Test extra arguments to XML#parse - :remove_pretty_printing.
751
+ # FIXME: How about a shorter (but still mnemonic) name for that ?
752
+ def test_parsing_nopp
753
+ a = "<foo><bar>100</bar><bar>200</bar></foo>"
754
+ b = "<foo>
755
+ <bar>
756
+ 100
757
+ </bar>
758
+ <bar>
759
+ 200
760
+ </bar>
761
+ </foo>"
762
+ c = XML.parse(a)
763
+ d = XML.parse(b)
764
+ e = XML.parse(b, :remove_pretty_printing => true)
765
+
766
+ assert_not_equal(c.to_s, d.to_s, "XML#parse should not ignore pretty printing by default")
767
+ assert_equal(c.to_s, e.to_s, "XML#parse(str, :remove_pretty_printing=>true) should work")
768
+ end
769
+
770
+ # Test XML.parse(str, :extra_entities => ...)
771
+ def test_parsing_entities
772
+ a = "<foo>&cat; &amp; &dog;</foo>"
773
+ b = XML.parse(a, :extra_entities => lambda{|e|
774
+ case e
775
+ when "cat"
776
+ "neko"
777
+ when "dog"
778
+ "inu"
779
+ end
780
+ })
781
+ c = XML.parse(a, :extra_entities => {"cat" => "neko", "dog" => "inu"})
782
+
783
+ assert_equal("neko & inu", b.text, "XML#parse(str, :extra_entities=>Proc) should work")
784
+ assert_equal("neko & inu", c.text, "XML#parse(str, :extra_entities=>Hash) should work")
785
+
786
+ d = XML.parse(a, :extra_entities => {"cat" => "neko", "dog" => "inu"})
787
+
788
+ # Central European characters escapes
789
+ e = "<foo>&zdot;&oacute;&lstrok;w</foo>"
790
+ f = XML.parse(e, :extra_entities => {"zdot" => 380, "oacute" => 243, "lstrok" => 322})
791
+
792
+ # Assumes \number does bytes, UTF8
793
+ assert_equal("\305\274\303\263\305\202w", f.text, "XML#parse(str, :extra_entities=>...) should work with integer codepoints")
794
+ end
795
+
796
+ # Test XML.load
797
+ def test_load
798
+ a = XML.load("test.xml")
799
+ b = XML.load(File.open("test.xml"))
800
+ c = XML.load("string:<foo><bar></bar></foo>")
801
+ d = XML.load("file:test.xml")
802
+
803
+ assert_equal("<foo><bar/></foo>", a.to_s, "XML#load should work")
804
+ assert_equal("<foo><bar/></foo>", b.to_s, "XML#load should work")
805
+ assert_equal("<foo><bar/></foo>", c.to_s, "XML#load should work")
806
+ assert_equal("<foo><bar/></foo>", d.to_s, "XML#load should work")
807
+ end
808
+
809
+ # Test multielement selectors
810
+ def test_multielement_selectors
811
+ a = XML.parse("<foo><bar color='blue'><x/></bar><bar color='red'><x><y i='1'/></x><y i='2'/></bar></foo>")
812
+ assert_equal("<x/><x><y i='1'/></x>", a.children(:bar, :x).to_s, "Multielement selectors should work")
813
+ assert_equal("<y i='2'/>", a.children(:bar, :y).to_s, "Multielement selectors should work")
814
+ assert_equal("<y i='1'/><y i='2'/>", a.children(:bar, :*, :y).to_s, "Multielement selectors should work")
815
+ assert_equal("<y i='1'/>", a.descendants(:x, :y).to_s, "Multielement selectors should work")
816
+ assert_equal("<y i='1'/><y i='2'/>", a.children(:bar, :*, :y).to_s, "Multielement selectors should work")
817
+ end
818
+
819
+ # Test deep_map
820
+ def test_deep_map
821
+ a = XML.parse("<foo><bar>x</bar> <foo><bar>y</bar></foo></foo>")
822
+ b = a.deep_map(:bar) {|c| XML.new(c.text.to_sym) }
823
+ assert_equal("<foo><x/> <foo><y/></foo></foo>", b.to_s, "XML#deep_map should work")
824
+
825
+ c = XML.parse("<foo><bar>x</bar> <bar><bar>y</bar></bar></foo>")
826
+ d = c.deep_map(:bar) {|c| XML.new(:xyz, c.attrs, *c.children) }
827
+ assert_equal("<foo><xyz>x</xyz> <xyz><bar>y</bar></xyz></foo>", d.to_s, "XML#deep_map should work")
828
+ end
829
+
830
+ # Test XML.load
831
+ def test_pretty_printer
832
+ a = XML.parse("<foo><bar>x</bar>Boo!<bar><y><z>f</z></y></bar><xyzzy /><bar>Mutiline\nText\n:-)</bar></foo>")
833
+ a.add_pretty_printing!
834
+ expected = "<foo>
835
+ <bar>
836
+ x
837
+ </bar>
838
+ Boo!
839
+ <bar>
840
+ <y>
841
+ <z>
842
+ f
843
+ </z>
844
+ </y>
845
+ </bar>
846
+ <xyzzy/>
847
+ <bar>
848
+ Mutiline
849
+ Text
850
+ :-)
851
+ </bar>
852
+ </foo>"
853
+ assert_equal(expected, a.to_s, "XML#pretty_print! should work")
854
+ end
855
+ end