PageRenderTime 65ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/test/rexml/test_core.rb

http://github.com/ruby/ruby
Ruby | 1468 lines | 1317 code | 95 blank | 56 comment | 2 complexity | 4f61a002bdf185df49f3f2e881f32399 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # coding: binary
  2. # frozen_string_literal: false
  3. require_relative "rexml_test_utils"
  4. require "rexml/document"
  5. require "rexml/parseexception"
  6. require "rexml/output"
  7. require "rexml/source"
  8. require "rexml/formatters/pretty"
  9. require "rexml/undefinednamespaceexception"
  10. require_relative "listener"
  11. module REXMLTests
  12. class Tester < Test::Unit::TestCase
  13. include REXMLTestUtils
  14. include REXML
  15. def setup
  16. @xsa_source = <<-EOL
  17. <?xml version="1.0"?>
  18. <?xsl stylesheet="blah.xsl"?>
  19. <!-- The first line tests the XMLDecl, the second tests PI.
  20. The next line tests DocType. This line tests comments. -->
  21. <!DOCTYPE xsa PUBLIC
  22. "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
  23. "http://www.garshol.priv.no/download/xsa/xsa.dtd">
  24. <xsa>
  25. <vendor id="blah">
  26. <name>Lars Marius Garshol</name>
  27. <email>larsga@garshol.priv.no</email>
  28. <url>http://www.stud.ifi.uio.no/~lmariusg/</url>
  29. </vendor>
  30. </xsa>
  31. EOL
  32. end
  33. def test_bad_markup
  34. [
  35. "<pkg='version'> foo </pkg>",
  36. '<0/>',
  37. '<a>&</a>',
  38. '<a>&a</a>',
  39. # '<a>&a;</a>', # FIXME
  40. '<a a="<"/>',
  41. '<a 3="<"/>',
  42. '<a a="1" a="2"/>',
  43. '<a><!-- -- --></a>',
  44. '<a><!-- ---></a>',
  45. '<a>&#x00;</a>',
  46. '<a>&#0;</a>',
  47. "<a a='&#0;' />",
  48. "<a>\f</a>",
  49. "<a a='\f' />",
  50. "<a>\000</a>",
  51. # FIXME '<a' + [65535].pack('U') + ' />',
  52. '<a>&#xfffe;</a>',
  53. '<a>&#65535;</a>',
  54. # FIXME '<a' + [0x0371].pack('U') + ' />',
  55. # FIXME '<a a' + [0x0371].pack('U') + '="" />',
  56. ].each do |src|
  57. assert_raise( ParseException, %Q{Parse #{src.inspect} should have failed!} ) do
  58. Document.new(src)
  59. end
  60. end
  61. end
  62. def test_attribute
  63. # Testing constructors
  64. #a = Attribute.new "hello", "dolly"
  65. #b = Attribute.new a
  66. #d = Document.new( "<a hello='dolly' href='blah'/>" )
  67. #c = d[0].attributes.get_attribute( "hello" )
  68. #assert_equal a, b
  69. #for attr in [ a, b, c]
  70. # assert_equal "hello", attr.name
  71. # assert_equal "dolly", attr.value
  72. #end
  73. # This because of a reported bug in attribute handling in 1.0a8
  74. source = '<a att="A">blah</a>'
  75. doc = Document.new source
  76. doc.elements.each do |a|
  77. a.attributes['att'] << 'B'
  78. assert_equal "AB", a.attributes['att']
  79. a.attributes['att'] = 'C'
  80. assert_equal "C", a.attributes['att']
  81. end
  82. # Bryan Murphy <murphybryanp@yahoo.com>
  83. text = "this is a {target[@name='test']/@value} test"
  84. source = <<-EOL
  85. <?xml version="1.0"?>
  86. <doc search="#{text}"/>
  87. EOL
  88. xml = Document.new source
  89. value = xml.root.attributes["search"]
  90. assert_equal text, value.to_s
  91. e = Element.new "test"
  92. e.add_attributes({ "name1" => "test1", "name4" => "test4" })
  93. e.add_attributes([["name3","test3"], ["name2","test2"]])
  94. assert_equal "test1", e.attributes["name1"]
  95. assert_equal "test2", e.attributes["name2"]
  96. assert_equal "test3", e.attributes["name3"]
  97. assert_equal "test4", e.attributes["name4"]
  98. # ensure that the attributes come out in sorted order
  99. assert_equal %w(<test
  100. name1='test1'
  101. name2='test2'
  102. name3='test3'
  103. name4='test4'/>).join(' '), e.to_s
  104. end
  105. def test_cdata
  106. test = "The quick brown fox jumped
  107. & < & < \" '
  108. over the lazy dog."
  109. source = "<a><![CDATA[#{test}]]></a>"
  110. d = REXML::Document.new( source )
  111. # Test constructors
  112. cdata = d[0][0]
  113. assert_equal test, cdata.value
  114. end
  115. def test_comment
  116. string = "This is a new comment!"
  117. source = "<!--#{string}-->"
  118. comment = Comment.new string
  119. REXML::Formatters::Default.new.write( comment, out = "" )
  120. assert_equal(source, out)
  121. comment2 = Comment.new comment
  122. assert_equal(comment, comment2)
  123. assert_raise(ParseException) {
  124. REXML::Document.new("<d><!- foo --></d>")
  125. }
  126. assert_raise(ParseException) {
  127. REXML::Document.new("<d><!-- foo -></d>")
  128. }
  129. end
  130. def test_whitespace
  131. doc = Document.new "<root-element><first-element/></root-element>"
  132. assert_equal 1, doc.root.size
  133. assert_equal 1, doc.root.elements.size
  134. doc = Document.new "<root-element>
  135. <first-element/>
  136. </root-element>"
  137. assert_equal 3, doc.root.size
  138. assert_equal 1, doc.root.elements.size
  139. text = " This is text
  140. with a lot of whitespace "
  141. source = "<a>#{text}<b>#{text}</b><c>#{text}</c>#{text}</a>"
  142. doc = Document.new( source, {
  143. :respect_whitespace => %w{ a c }
  144. } )
  145. assert_equal text, doc.elements["//c"].text
  146. string = ""
  147. doc.root.each { |n| string << n.to_s if n.kind_of? Text }
  148. assert_equal text+text, string
  149. string =" lots of blank
  150. space"
  151. doc.root.add_element("d").add_element("c").text = string
  152. doc.root.add_element("e").text = string
  153. assert_equal string, doc.elements["/a/d/c"].text
  154. assert string != doc.elements["/a/e"].text, "Text wasn't properly compressed"
  155. doc = Document.new source, { :respect_whitespace => :all }
  156. doc.root.add_element("d").text = string
  157. assert_equal text, doc.root.text
  158. nxt = ""
  159. doc.root.each { |n| nxt << n.to_s if n.kind_of? Text }
  160. assert_equal text+text, nxt
  161. assert_equal text, doc.root.elements["b"].text
  162. assert_equal text, doc.root.elements["c"].text
  163. assert_equal string, doc.root.elements["d"].text
  164. end
  165. # This isn't complete. We need to check declarations and comments
  166. def test_doctype
  167. string = "something"
  168. correct = "<!DOCTYPE something>"
  169. doc = DocType.new(string)
  170. assert_equal(string, doc.name)
  171. doc.write(out="")
  172. assert_equal(correct, out)
  173. doc2 = DocType.new(doc)
  174. assert_equal(doc.name, doc2.name)
  175. assert_equal(doc.external_id, doc2.external_id)
  176. correct = '<!DOCTYPE xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML" "http://www.garshol.priv.no/download/xsa/xsa.dtd">'
  177. one_line_source = '<!DOCTYPE xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML" "http://www.garshol.priv.no/download/xsa/xsa.dtd"><a/>'
  178. doc = Document.new( one_line_source )
  179. doc = doc[0]
  180. assert(doc)
  181. doc.write(test="")
  182. assert_equal(correct, test)
  183. multi_line_source = '<!DOCTYPE xsa PUBLIC
  184. "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
  185. "http://www.garshol.priv.no/download/xsa/xsa.dtd">
  186. <a/>'
  187. d = Document.new( multi_line_source )
  188. doc = d[0]
  189. assert(doc)
  190. doc.write(test="")
  191. assert_equal(correct, test)
  192. odd_space_source = ' <!DOCTYPE
  193. xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
  194. "http://www.garshol.priv.no/download/xsa/xsa.dtd"> <a/>'
  195. d = Document.new( odd_space_source )
  196. dt = d.doctype
  197. dt.write(test="")
  198. assert_equal(correct, test)
  199. # OK, the BIG doctype test, numba wun
  200. doc = File.open(fixture_path("doctype_test.xml")) do |docin|
  201. Document.new(docin)
  202. end
  203. doc.write(test="")
  204. assert_equal(31, doc.doctype.size)
  205. end
  206. def test_document
  207. # Testing cloning
  208. source = "<element/>"
  209. doc = Document.new source
  210. # Testing Root
  211. assert_equal doc.root.name.to_s, "element"
  212. # Testing String source
  213. source = @xsa_source
  214. doc = Document.new source
  215. assert_instance_of XMLDecl, doc.xml_decl
  216. assert_instance_of DocType, doc.doctype
  217. assert_equal doc.version, "1.0"
  218. doc = File.open(fixture_path("dash.xml")) {|s| Document.new s }
  219. assert_equal "content-2", doc.elements["//content-2"].name
  220. end
  221. def test_instruction
  222. target = "use"
  223. content = "ruby"
  224. source = "<?#{target} #{content}?>"
  225. instruction = Instruction.new target, content
  226. instruction2 = Instruction.new instruction
  227. assert_equal(instruction, instruction2)
  228. REXML::Formatters::Default.new.write( instruction, out = "" )
  229. assert_equal(source, out)
  230. d = Document.new( source )
  231. instruction2 = d[0]
  232. assert_equal(instruction.to_s, instruction2.to_s)
  233. assert_raise(ParseException) {
  234. REXML::Document.new("<d><?foo bar></d>")
  235. }
  236. end
  237. def test_parent
  238. parent = Parent.new
  239. begin
  240. parent << "Something"
  241. rescue Exception
  242. parent << Comment.new("Some comment")
  243. assert parent.size == 1, "size of parent should be 1"
  244. else
  245. assert_fail "should have gotten an exception trying to add a "+ "String to a Parent"
  246. end
  247. source = "<a><one/><three/><five/></a>"
  248. doc = Document.new source
  249. three = doc.root.elements["three"]
  250. doc.root.insert_before( three, Element.new("two") )
  251. nxt = doc.root.elements["one"]
  252. string = ""
  253. while nxt
  254. string << nxt.name
  255. nxt = nxt.next_sibling
  256. end
  257. assert_equal "onetwothreefive", string
  258. doc.root.insert_after( three, Element.new("four") )
  259. string = ""
  260. doc.root.each { |element| string << element.name }
  261. assert_equal "onetwothreefourfive", string
  262. string = ""
  263. nxt = doc.root.elements["five"]
  264. while nxt
  265. string << nxt.name
  266. nxt = nxt.previous_sibling
  267. end
  268. assert_equal "fivefourthreetwoone", string
  269. doc.insert_after "//two", Element.new("two-and-half")
  270. string = doc.root.elements.collect {|x| x.name}.join
  271. assert_equal "onetwotwo-and-halfthreefourfive", string
  272. doc.elements["/a/five"].insert_before "../four", Element.new("three-and-half")
  273. string = doc.root.elements.collect {|x| x.name}.join
  274. assert_equal "onetwotwo-and-halfthreethree-and-halffourfive", string
  275. doc.elements["/a/five"].previous_sibling = Element.new("four-and-half")
  276. string = doc.root.elements.collect {|x| x.name}.join
  277. assert_equal "onetwotwo-and-halfthreethree-and-halffourfour-and-halffive", string
  278. doc.elements["/a/one"].next_sibling = Element.new("one-and-half")
  279. string = doc.root.elements.collect {|x| x.name}.join
  280. assert_equal "oneone-and-halftwotwo-and-halfthreethree-and-halffourfour-and-halffive", string
  281. doc = Document.new "<a><one/><three/></a>"
  282. doc.root[1,0] = Element.new "two"
  283. string = ""
  284. doc.root.each { |el| string << el.name }
  285. assert_equal "onetwothree", string
  286. end
  287. # The Source classes are tested extensively throughout the test suite
  288. def test_source
  289. # Testing string source
  290. source = @xsa_source
  291. doc = Document.new source
  292. assert_equal doc.root.name.to_s, "xsa"
  293. # Testing IO source
  294. doc = File.open(fixture_path("project.xml")) {|f| Document.new f }
  295. assert_equal doc.root.name.to_s, "Project"
  296. end
  297. def test_text
  298. f = REXML::Formatters::Default.new
  299. string = "Some text"
  300. text = Text.new(string)
  301. assert_equal(string, text.to_s)
  302. text2 = Text.new(text)
  303. assert_equal(text, text2)
  304. #testing substitution
  305. string = "0 < ( 1 & 1 )"
  306. correct = "0 &lt; ( 1 &amp; 1 )"
  307. text = Text.new(string, true)
  308. f.write(text,out="")
  309. assert_equal(correct, out)
  310. string = "Cats &amp; dogs"
  311. text = Text.new(string, false, nil, true)
  312. assert_equal(string, text.to_s)
  313. string2 = "<a>#{string}</a>"
  314. doc = Document.new( string2, {
  315. :raw => %w{ a b }
  316. } )
  317. f.write(doc,out="")
  318. assert_equal(string2, out)
  319. b = doc.root.add_element( "b" )
  320. b.text = string
  321. assert_equal(string, b.get_text.to_s)
  322. c = doc.root.add_element("c")
  323. c.text = string
  324. assert_equal("Cats &amp;amp; dogs", c.get_text.to_s)
  325. # test all
  326. string = "<a>&amp;<b>&lt;</b><c>&gt;<d>&quot;</d></c></a>"
  327. doc = Document.new(string, { :raw => :all })
  328. assert_equal( "&amp;", doc.elements["/a"][0].to_s )
  329. assert_equal( "&", doc.elements["/a"].text )
  330. assert_equal( "&lt;", doc.elements["/a/b"][0].to_s )
  331. assert_equal( "<", doc.elements["/a/b"].text )
  332. assert_equal( "&gt;", doc.elements["/a/c"][0].to_s )
  333. assert_equal( ">", doc.elements["/a/c"].text )
  334. assert_equal( '&quot;', doc.elements["//d"][0].to_s )
  335. assert_equal( '"', doc.elements["//d"].text )
  336. # test some other stuff
  337. doc = Document.new('<a><b/></a>')
  338. doc.root.text = 'Sean'
  339. assert_equal( '<a><b/>Sean</a>', doc.to_s )
  340. doc.root.text = 'Elliott'
  341. assert_equal( '<a><b/>Elliott</a>', doc.to_s )
  342. doc.root.add_element( 'c' )
  343. assert_equal( '<a><b/>Elliott<c/></a>', doc.to_s )
  344. doc.root.text = 'Russell'
  345. assert_equal( '<a><b/>Russell<c/></a>', doc.to_s )
  346. doc.root.text = nil
  347. assert_equal( '<a><b/><c/></a>', doc.to_s )
  348. end
  349. def test_text_frozen
  350. string = "Frozen".freeze
  351. text = Text.new(string)
  352. assert_equal(string, text.to_s)
  353. end
  354. def test_xmldecl
  355. source = "<?xml version='1.0'?>"
  356. # test args
  357. # test no args
  358. decl2 = XMLDecl.new
  359. assert_equal source, decl2.to_s
  360. # test XMLDecl
  361. decl2 = XMLDecl.new "1.0"
  362. assert_equal source, decl2.to_s
  363. end
  364. def test_xmldecl_utf_16be_encoding_name
  365. assert_equal("<?xml version='1.0' encoding='UTF-16'?>",
  366. XMLDecl.new("1.0", "UTF-16").to_s)
  367. end
  368. def each_test( element, xpath, num_children )
  369. count = 0
  370. element.each_element( xpath ) { |child|
  371. count += 1
  372. yield child if block_given?
  373. }
  374. assert_equal num_children, count
  375. end
  376. # This is the biggest test, as the number of permutations of xpath are
  377. # enormous.
  378. def test_element_access
  379. # Testing each_element
  380. doc = File.open(fixture_path("project.xml")) {|f| Document.new f }
  381. each_test( doc, "/", 1 ) { |child|
  382. assert_equal doc.name, child.name
  383. }
  384. each_test(doc, ".", 1) { |child| assert_equal doc, child }
  385. each_test(doc.root, "..", 1) { |child| assert_equal doc, child }
  386. each_test(doc.root, "*", 5)
  387. each_test(doc, "Project/Datasets", 1) { |child|
  388. assert_equal "Datasets", child.name
  389. }
  390. each_test(doc, "Project/Datasets/link", 2 )
  391. each_test(doc.root, "/Project/Description", 1) {|child|
  392. assert_equal "Description", child.name
  393. }
  394. each_test(doc.root, "./Description",1 ) { |child|
  395. assert_equal "Description",child.name
  396. }
  397. each_test(doc.root, "../Project",1 ) { |child|
  398. assert_equal doc.root, child
  399. }
  400. #each_test(doc,".../link",2) {|child| assert_equal "link",child.name.to_s}
  401. # test get_element
  402. first = doc.elements[ "Project" ]
  403. assert_equal doc.root, first
  404. second = doc.elements[ "Project" ].elements[1]
  405. third = doc.elements[ "Project/Creator" ]
  406. assert_equal second, third
  407. fourth = doc.elements[ "Project/Datasets/link[@idref='18']" ]
  408. assert_equal "Test data 1", fourth.attributes["name"]
  409. # Testing each_predicate
  410. each_test( doc, "Project/Datasets/link[@idref='18']", 1 ) { |child|
  411. assert_equal "Test data 1", child.attributes["name"]
  412. }
  413. # testing next/previous_element
  414. creator = doc.elements["//Creator"]
  415. lm = creator.next_element
  416. assert_equal "LastModifier", lm.name
  417. assert_equal "Creator", lm.previous_element.name
  418. end
  419. def test_child
  420. sean = Element.new "Sean"
  421. rubbell = Element.new "Rubbell"
  422. elliott = sean.add_element "Elliott"
  423. sean << rubbell
  424. assert_equal elliott, rubbell.previous_sibling
  425. assert_equal rubbell, elliott.next_sibling
  426. russell = Element.new "Russell"
  427. rubbell.replace_with russell
  428. assert_equal elliott, russell.previous_sibling
  429. assert_equal russell, elliott.next_sibling
  430. assert_nil russell.document
  431. assert_equal sean, russell.root
  432. end
  433. # Most of this class is tested elsewhere. Here are the methods which
  434. # aren't used in any other class
  435. def test_element
  436. sean = Element.new "Sean"
  437. string = "1) He's a great guy!"
  438. sean.text = string
  439. russell = Element.new "Russell"
  440. sean << russell
  441. russell.attributes["email"] = "ser@germane-software.com"
  442. assert_equal russell.attributes["email"], "ser@germane-software.com"
  443. russell.attributes["webpage"] = "http://www.germane-software.com/~ser"
  444. assert sean.has_text?, "element should have text"
  445. assert_equal sean.text, string
  446. assert sean.has_elements?, "element should have one element"
  447. string = "2) What a stud!"
  448. sean.add_text string
  449. sean.text = "3) Super programmer!"
  450. sean.text = nil
  451. assert sean.has_text?, "element should still have text"
  452. assert_equal sean.text, string
  453. russell.delete_attribute "email"
  454. assert_nil russell.attributes["email"]
  455. russell.attributes.delete "webpage"
  456. assert !russell.has_attributes?, "element should have no attributes"
  457. end
  458. def test_no_format
  459. source = "<a><b><c>blah</c><d/></b></a>"
  460. out = ""
  461. doc = Document.new( source )
  462. doc.write(out)
  463. assert_equal(source, out)
  464. end
  465. def test_namespace
  466. source = <<-EOF
  467. <x xmlns:foo="http://www.bar.com/schema">
  468. </x>
  469. EOF
  470. doc = Document.new(source)
  471. assert_equal("http://www.bar.com/schema", doc.root.namespace( "foo" ))
  472. source = <<-EOF
  473. <!-- bar namespace is "someuri" -->
  474. <foo:bar xmlns="default" xmlns:foo="someuri">
  475. <!-- a namespace is "default" -->
  476. <a/>
  477. <!-- foo:b namespace is "someuri" -->
  478. <foo:b>
  479. <!-- c namespace is "default" -->
  480. <c/>
  481. </foo:b>
  482. <!-- d namespace is "notdefault" -->
  483. <d xmlns="notdefault">
  484. <!-- e namespace is "notdefault" -->
  485. <e/>
  486. <f xmlns="">
  487. <g/>
  488. </f>
  489. </d>
  490. </foo:bar>
  491. EOF
  492. doc = Document.new source
  493. assert_equal "someuri", doc.root.namespace
  494. assert_equal "default", doc.root.elements[1].namespace
  495. assert_equal "someuri", doc.root.elements[2].namespace
  496. assert_equal "notdefault", doc.root.elements[ 3 ].namespace
  497. # Testing namespaces in attributes
  498. source = <<-EOF
  499. <a xmlns:b="uri">
  500. <b b:a="x" a="y"/>
  501. <c xmlns="foo">
  502. </c>
  503. </a>
  504. EOF
  505. doc = Document.new source
  506. b = doc.root.elements["b"]
  507. assert_equal "x", b.attributes["b:a"]
  508. assert_equal "y", b.attributes["a"]
  509. doc = Document.new
  510. doc.add_element "sean:blah"
  511. doc.root.text = "Some text"
  512. out = ""
  513. doc.write(out)
  514. assert_equal "<sean:blah>Some text</sean:blah>", out
  515. end
  516. def test_add_namespace
  517. e = Element.new 'a'
  518. e.add_namespace 'someuri'
  519. e.add_namespace 'foo', 'otheruri'
  520. e.add_namespace 'xmlns:bar', 'thirduri'
  521. assert_equal 'someuri', e.attributes['xmlns']
  522. assert_equal 'otheruri', e.attributes['xmlns:foo']
  523. assert_equal 'thirduri', e.attributes['xmlns:bar']
  524. end
  525. def test_big_documentation
  526. d = File.open(fixture_path("documentation.xml")) {|f| Document.new f }
  527. assert_equal "Sean Russell", d.elements["documentation/head/author"].text.tr("\n\t", " ").squeeze(" ")
  528. out = ""
  529. d.write out
  530. end
  531. def test_tutorial
  532. doc = File.open(fixture_path("tutorial.xml")) {|f| Document.new f }
  533. out = ""
  534. doc.write out
  535. end
  536. def test_stream
  537. c = Listener.new
  538. File.open(fixture_path("documentation.xml")) do |f|
  539. Document.parse_stream( f, c )
  540. end
  541. assert(c.ts, "Stream parsing apparently didn't parse the whole file")
  542. assert(c.te, "Stream parsing dropped end tag for documentation")
  543. Document.parse_stream("<a.b> <c/> </a.b>", c)
  544. Document.parse_stream("<a>&lt;&gt;&amp;</a>", c)
  545. assert_equal('<>&', c.normalize)
  546. end
  547. def test_line
  548. f = File.new(fixture_path("bad.xml"))
  549. Document.new f
  550. assert_fail "There should have been an error"
  551. rescue Exception
  552. # We should get here
  553. assert($!.line == 5, "Should have been an error on line 5, "+
  554. "but was reported as being on line #{$!.line}" )
  555. ensure
  556. f.close if f
  557. end
  558. def test_substitution
  559. val = "a'b\"c"
  560. el = Element.new("a")
  561. el.attributes["x"] = val
  562. REXML::Formatters::Default.new.write(el, out="")
  563. nel = Document.new( out)
  564. assert_equal( val, nel.root.attributes["x"] )
  565. end
  566. def test_exception
  567. source = SourceFactory.create_from "<a/>"
  568. p = ParseException.new( "dummy message", source )
  569. begin
  570. raise "dummy"
  571. rescue Exception
  572. p.continued_exception = $!
  573. end
  574. end
  575. def test_bad_content
  576. in_gt = '<root-el>content>content</root-el>'
  577. in_lt = '<root-el>content<content</root-el>'
  578. # This is OK
  579. tree_gt = Document.new in_gt
  580. assert_equal "content>content", tree_gt.elements[1].text
  581. # This isn't
  582. begin
  583. Document.new in_lt
  584. assert_fail "Should have gotten a parse error"
  585. rescue ParseException
  586. end
  587. end
  588. def test_iso_8859_1_output_function
  589. out = ""
  590. output = Output.new( out )
  591. koln_iso_8859_1 = "K\xF6ln"
  592. koln_utf8 = "K\xc3\xb6ln"
  593. source = Source.new( koln_iso_8859_1, 'iso-8859-1' )
  594. results = source.scan(/.*/)[0]
  595. koln_utf8.force_encoding('UTF-8') if koln_utf8.respond_to?(:force_encoding)
  596. assert_equal koln_utf8, results
  597. output << results
  598. if koln_iso_8859_1.respond_to?(:force_encoding)
  599. koln_iso_8859_1.force_encoding('ISO-8859-1')
  600. end
  601. assert_equal koln_iso_8859_1, out
  602. end
  603. def test_attributes_each
  604. doc = Document.new("<a xmlns:a='foo'><b x='1' y='2' z='3' a:x='4'/></a>")
  605. count = 0
  606. doc.root.elements[1].attributes.each {|k,v| count += 1 }
  607. assert_equal 4, count
  608. end
  609. def test_delete_namespace
  610. doc = Document.new "<a xmlns='1' xmlns:x='2'/>"
  611. doc.root.delete_namespace
  612. doc.root.delete_namespace 'x'
  613. assert_equal "<a/>", doc.to_s
  614. end
  615. def test_each_element_with_attribute
  616. doc = Document.new "<a><b id='1'/><c id='2'/><d id='1'/><e/></a>"
  617. arry = []
  618. block = proc { |e|
  619. assert arry.include?(e.name)
  620. arry.delete e.name
  621. }
  622. # Yields b, c, d
  623. arry = %w{b c d}
  624. doc.root.each_element_with_attribute( 'id', &block )
  625. assert_equal 0, arry.size
  626. # Yields b, d
  627. arry = %w{b d}
  628. doc.root.each_element_with_attribute( 'id', '1', &block )
  629. assert_equal 0, arry.size
  630. # Yields b
  631. arry = ['b']
  632. doc.root.each_element_with_attribute( 'id', '1', 1, &block )
  633. assert_equal 0, arry.size
  634. # Yields d
  635. arry = ['d']
  636. doc.root.each_element_with_attribute( 'id', '1', 0, 'd', &block )
  637. assert_equal 0, arry.size
  638. end
  639. def test_each_element_with_text
  640. doc = Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
  641. arry = []
  642. block = proc { |e|
  643. assert arry.include?(e.name)
  644. arry.delete e.name
  645. }
  646. # Yields b, c, d
  647. arry = %w{b c d}
  648. doc.root.each_element_with_text(&block)
  649. assert_equal 0, arry.size
  650. # Yields b, d
  651. arry = %w{b c}
  652. doc.root.each_element_with_text( 'b', &block )
  653. assert_equal 0, arry.size
  654. # Yields b
  655. arry = ['b']
  656. doc.root.each_element_with_text( 'b', 1, &block )
  657. assert_equal 0, arry.size
  658. # Yields d
  659. arry = ['d']
  660. doc.root.each_element_with_text( nil, 0, 'd', &block )
  661. assert_equal 0, arry.size
  662. end
  663. def test_element_parse_stream
  664. s = Source.new( "<a>some text</a>" )
  665. l = Listener.new
  666. class << l
  667. def tag_start name, attributes
  668. raise "Didn't find proper tag name" unless 'a'==name
  669. end
  670. end
  671. Document::parse_stream(s, l)
  672. end
  673. def test_deep_clone
  674. a = Document.new( '<?xml version="1"?><a x="y"><b>text</b>text<c><d><e>text</e></d></c></a>' )
  675. b = a.deep_clone
  676. assert_equal a.to_s, b.to_s
  677. a = Document.new( '<a>some &lt; text <b> more &gt; text </b> &gt; </a>' )
  678. b = a.deep_clone
  679. assert_equal a.to_s, b.to_s
  680. c = Document.new( b.to_s )
  681. assert_equal a.to_s, c.to_s
  682. end
  683. def test_whitespace_before_root
  684. a = <<EOL
  685. <?xml version='1.0'?>
  686. <blo>
  687. <wak>
  688. </wak>
  689. </blo>
  690. EOL
  691. d = Document.new(a)
  692. b = ""
  693. d.write( b )
  694. assert_equal a,b
  695. end
  696. def test_entities
  697. a = Document.new( '<a>&#101;&#x65;&#252;</a>' )
  698. assert_equal('eeĂź'.force_encoding("UTF-8"), a.root.text)
  699. end
  700. def test_element_decl
  701. element_decl = Source.new("<!DOCTYPE foo [
  702. <!ELEMENT bar (#PCDATA)>
  703. ]>")
  704. doc = Document.new( element_decl )
  705. d = doc[0]
  706. assert_equal("<!ELEMENT bar (#PCDATA)>", d.to_s.split(/\n/)[1].strip)
  707. end
  708. def test_attlist_decl
  709. doc = Document.new <<-EOL
  710. <!DOCTYPE blah [
  711. <!ATTLIST blah
  712. xmlns CDATA "foo">
  713. <!ATTLIST a
  714. bar CDATA "gobble"
  715. xmlns:one CDATA "two"
  716. >
  717. ]>
  718. <a xmlns:three='xxx' three='yyy'><one:b/><three:c/></a>
  719. EOL
  720. assert_equal 'gobble', doc.root.attributes['bar']
  721. assert_equal 'xxx', doc.root.elements[2].namespace
  722. assert_equal 'two', doc.root.elements[1].namespace
  723. assert_equal 'foo', doc.root.namespace
  724. doc = Document.new <<-EOL
  725. <?xml version="1.0"?>
  726. <!DOCTYPE schema SYSTEM "XMLSchema.dtd" [
  727. <!ENTITY % p ''>
  728. <!ENTITY % s ''>
  729. <!ATTLIST schema
  730. xmlns:svg CDATA #FIXED "http://www.w3.org/2000/svg"
  731. xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"
  732. xmlns:xml CDATA #FIXED "http://www.w3.org/XML/1998/namespace"
  733. >]>
  734. <schema/>
  735. EOL
  736. prefixes = doc.root.prefixes.sort
  737. correct = ['svg', 'xlink', 'xml']
  738. assert_equal correct, prefixes
  739. end
  740. def test_attlist_write
  741. doc = File.open(fixture_path("foo.xml")) {|file| Document.new file }
  742. out = ''
  743. doc.write(out)
  744. end
  745. def test_more_namespaces
  746. assert_raise( REXML::UndefinedNamespaceException,
  747. %Q{Should have gotten an Undefined Namespace error} ) {
  748. Document.new("<r><p><n:c/></p></r>")
  749. }
  750. doc2 = Document.new("<r xmlns:n='1'><p><n:c/></p></r>")
  751. es = XPath.match(doc2, '//c')
  752. assert_equal 0, es.size
  753. es = XPath.match(doc2, '//n:c')
  754. assert_equal 1, es.size
  755. doc2.root.add_namespace('m', '2')
  756. doc2.root.add_element("m:o")
  757. es = XPath.match(doc2, './/o')
  758. assert_equal 0, es.size
  759. es = XPath.match(doc2, '//n:c')
  760. assert_equal 1, es.size
  761. end
  762. def test_ticket_51
  763. doc = REXML::Document.new <<-EOL
  764. <test xmlns='1' xmlns:x='1'>
  765. <a>X</a>
  766. <x:a>Y</x:a>
  767. <b xmlns='2'>
  768. <a>Z</a>
  769. </b>
  770. </test>
  771. EOL
  772. # The most common case. People not caring about the namespaces much.
  773. assert_equal( "XY", XPath.match( doc, "/test/a/text()" ).join )
  774. assert_equal( "XY", XPath.match( doc, "/test/x:a/text()" ).join )
  775. # Surprising? I don't think so, if you believe my definition of the "common case"
  776. assert_equal( "XYZ", XPath.match( doc, "//a/text()" ).join )
  777. # These are the uncommon cases. Namespaces are actually important, so we define our own
  778. # mappings, and pass them in.
  779. assert_equal( "XY", XPath.match( doc, "/f:test/f:a/text()", { "f" => "1" } ).join )
  780. # The namespaces are defined, and override the original mappings
  781. assert_equal( "", XPath.match( doc, "/test/a/text()", { "f" => "1" } ).join )
  782. assert_equal( "", XPath.match( doc, "/x:test/x:a/text()", { "f" => "1" } ).join )
  783. assert_equal( "", XPath.match( doc, "//a/text()", { "f" => "1" } ).join )
  784. end
  785. def test_processing_instruction
  786. d = Document.new("<a><?foo bar?><?foo2 bar2?><b><?foo3 bar3?></b><?foo4 bar4?></a>")
  787. assert_equal 4, XPath.match(d, '//processing-instruction()' ).size
  788. match = XPath.match(d, "//processing-instruction('foo3')" )
  789. assert_equal 1, match.size
  790. assert_equal 'bar3', match[0].content
  791. end
  792. def test_oses_with_bad_EOLs
  793. Document.new("\n\n\n<?xml version='1.0'?>\n\n\n<a/>\n\n")
  794. end
  795. # Contributed (with patch to fix bug) by Kouhei
  796. def test_ignore_whitespace
  797. source = "<a> <b/> abc <![CDATA[def]]> </a>"
  798. context_all = {:ignore_whitespace_nodes => :all}
  799. context_a = {:ignore_whitespace_nodes => %(a)}
  800. context_b = {:ignore_whitespace_nodes => %(b)}
  801. tests = [[[" abc ", "def"], context_all],
  802. [[" abc ", "def"], context_a],
  803. [[" ", " abc ", "def", " "], context_b]]
  804. tests.each do |test|
  805. assert_equal(test[0], Document.new(source, test[1]).root.texts.collect{|x|
  806. x.to_s})
  807. end
  808. end
  809. def test_0xD_in_preface
  810. doc = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\x0D<opml version=\"1.0\">\x0D</opml>"
  811. doc = Document.new doc
  812. end
  813. def test_hyphens_in_doctype
  814. doc = REXML::Document.new <<-EOQ
  815. <?xml version="1.0"?>
  816. <!DOCTYPE a-b-c>
  817. <a-b-c>
  818. <a/>
  819. </a-b-c>
  820. EOQ
  821. assert_equal('a-b-c', doc.doctype.name)
  822. end
  823. def test_accents
  824. docs = [
  825. %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
  826. <gnuPod>
  827. <files>
  828. <file id="57" artist="Coralie Cl\357\277\275ent" />
  829. </files>
  830. </gnuPod>},
  831. '<?xml version="1.0" encoding="ISO-8859-1"?>
  832. <gnuPod>
  833. <files>
  834. <file id="71" album="Astrakan Caf" />
  835. </files>
  836. </gnuPod>',
  837. %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
  838. <gnuPod>
  839. <files>
  840. <file id="71" album="Astrakan Caf\357\277\275eria" />
  841. </files>
  842. </gnuPod>},
  843. %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
  844. <gnuPod>
  845. <files>
  846. <file id="71" album="Astrakan Caf\357\277\275" />
  847. </files>
  848. </gnuPod>} ]
  849. docs.each_with_index { |d,i|
  850. begin
  851. REXML::Document.new(d)
  852. rescue
  853. puts "#{i} => #{docs[i]}"
  854. raise
  855. end
  856. }
  857. end
  858. def test_replace_text
  859. e = REXML::Element.new( "a" )
  860. e.add_text( "foo" )
  861. assert_equal( "<a>foo</a>", e.to_s )
  862. e[0].value = "bar"
  863. assert_equal( "<a>bar</a>", e.to_s )
  864. e[0].value = "<"
  865. assert_equal( "<a>&lt;</a>", e.to_s )
  866. assert_equal( "<", e[0].value )
  867. end
  868. def test_write_doctype
  869. ## XML Document and Declaration
  870. document = REXML::Document.new
  871. xmldecl = REXML::XMLDecl.new("1.0", "UTF-8")
  872. document.add(xmldecl)
  873. s = ""
  874. document.write(s)
  875. ## XML Doctype
  876. str = '<!DOCTYPE foo "bar">'
  877. source = REXML::Source.new(str)
  878. doctype = REXML::DocType.new(source)
  879. document.add(doctype)
  880. document.write(s)
  881. ## Element
  882. element = REXML::Element.new("hoge")
  883. document.add(element)
  884. document.write(s)
  885. end
  886. def test_write_cdata
  887. src = "<a>A</a>"
  888. doc = REXML::Document.new( src )
  889. out = ""
  890. doc.write( out )
  891. assert_equal( src, out )
  892. src = "<a><![CDATA[A]]></a>"
  893. doc = REXML::Document.new( src )
  894. out = ""
  895. doc.write( out )
  896. assert_equal( src, out )
  897. end
  898. def test_namespace_attributes
  899. source = <<-EOL
  900. <a xmlns:x="1">
  901. <x:b x:n="foo"/>
  902. </a>
  903. EOL
  904. d = Document.new( source )
  905. assert_equal( 'foo', REXML::XPath.first(d.root, "//x:b/@x:n").value )
  906. assert_equal( nil, REXML::XPath.first(d.root, "//x:b/@x:n", {}))
  907. end
  908. def test_null_element_name
  909. a = REXML::Document.new
  910. assert_raise( RuntimeError ) {
  911. a.add_element( nil )
  912. }
  913. end
  914. def test_text_raw
  915. # From the REXML tutorial
  916. # (http://www.germane-software.com/software/rexml/test/data/tutorial.html)
  917. doc = Document.new <<-EOL
  918. <?xml version="1.0"?>
  919. <!DOCTYPE schema SYSTEM "XMLSchema.dtd" [
  920. <!ENTITY % s 'Sean'>
  921. ]>
  922. <a/>
  923. EOL
  924. a = doc.root
  925. # This makes sure that RAW text nodes don't have their entity strings
  926. # replaced
  927. t = Text.new "Sean", false, nil, true
  928. a.text = t
  929. assert_equal( "Sean", t.to_s )
  930. assert_equal( "Sean", t.value )
  931. # This makes sure that they do
  932. t = Text.new "Sean", false, nil, false
  933. a.text = t
  934. assert_equal( "&s;", t.to_s )
  935. assert_equal( "Sean", t.value )
  936. t = Text.new "&s;", false, nil, true
  937. a.text = t
  938. assert_equal( "&s;", t.to_s )
  939. assert_equal( "Sean", t.value )
  940. t = Text.new "&s;", false, nil, true
  941. a.text = t
  942. assert_equal( "&s;", t.to_s )
  943. assert_equal( "Sean", t.value )
  944. # Ticket #44
  945. t = REXML::Text.new( "&amp;", false, nil, true )
  946. assert_equal( "&amp;", t.to_s )
  947. t = REXML::Text.new("&amp;", false, false)
  948. assert_equal( "&amp;amp;", t.to_s )
  949. end
  950. def test_to_xpath
  951. doc = REXML::Document.new( %q{<tag1>
  952. <tag2 name="tag2"/>
  953. <tag2 name="tag2"/>
  954. </tag1>})
  955. names = %w{ /tag1/tag2[1] /tag1/tag2[2] }
  956. doc.root.elements.each_with_index {|el, i|
  957. assert_equal( names[i], el.xpath )
  958. }
  959. end
  960. def test_transitive
  961. doc = REXML::Document.new( "<a/>")
  962. s = ""
  963. doc.write( s, 0, true )
  964. end
  965. # This is issue #40
  966. def test_replace_with
  967. old = '<doc>old<foo/>old</doc>'
  968. d = REXML::Document.new(old).root
  969. new = REXML::Text.new('new',true,nil,true)
  970. child = d.children[2]
  971. child.replace_with(new)
  972. assert_equal( new, d.children[2] )
  973. end
  974. def test_repeated_writes
  975. a = IO.read(fixture_path("iso8859-1.xml"))
  976. f = REXML::Formatters::Pretty.new
  977. xmldoc = REXML::Document.new( a )
  978. a_andre = xmldoc.elements['//image'].attributes['caption']
  979. f.write(xmldoc,b="")
  980. xmldoc = REXML::Document.new(b)
  981. b_andre = xmldoc.elements['//image'].attributes['caption']
  982. assert_equal( a_andre, b_andre )
  983. f.write(xmldoc,c="")
  984. xmldoc = REXML::Document.new(c)
  985. c_andre = xmldoc.elements['//image'].attributes['caption']
  986. assert_equal( b_andre, c_andre )
  987. o = Output.new(d="","UTF-8")
  988. f.write(xmldoc,o)
  989. assert_not_equal( c, d )
  990. end
  991. def test_pretty_format_long_text_finite
  992. n = 1_000_000
  993. long_text = 'aaaa ' * n
  994. xml = "<doc>#{long_text}</doc>"
  995. formatter = REXML::Formatters::Pretty.new
  996. document = nil
  997. begin
  998. document = REXML::Document.new(xml)
  999. rescue REXML::ParseException
  1000. skip_message = "skip this test because we can't check Pretty#wrap " +
  1001. "works without #<SystemStackError: stack level too deep> on " +
  1002. "small memory system. #<RegexpError: failed to allocate memory> " +
  1003. "will be raised on the system. See also [ruby-dev:42599]."
  1004. return skip_message
  1005. end
  1006. output = ""
  1007. formatter.write(document, output)
  1008. assert_equal("<doc>\n" +
  1009. ((" " + (" aaaa" * 15) + "\n") * (n / 15)) +
  1010. " " + ("aaaa " * (n % 15)) + "\n" +
  1011. "</doc>",
  1012. output)
  1013. end
  1014. def test_pretty_format_deep_indent
  1015. n = 6
  1016. elements = ""
  1017. n.times do |i|
  1018. elements << "<element#{i}>"
  1019. elements << "element#{i} " * 5
  1020. end
  1021. (n - 1).downto(0) do |i|
  1022. elements << "</element#{i}>"
  1023. end
  1024. xml = "<doc>#{elements}</doc>"
  1025. document = REXML::Document.new(xml)
  1026. formatter = REXML::Formatters::Pretty.new
  1027. formatter.width = 20
  1028. output = ""
  1029. formatter.write(document, output)
  1030. assert_equal(<<-XML.strip, output)
  1031. <doc>
  1032. <element0>
  1033. element0
  1034. element0
  1035. element0
  1036. element0
  1037. element0\s
  1038. <element1>
  1039. element1
  1040. element1
  1041. element1
  1042. element1
  1043. element1\s
  1044. <element2>
  1045. element2
  1046. element2
  1047. element2
  1048. element2
  1049. element2\s
  1050. <element3>
  1051. element3
  1052. element3
  1053. element3
  1054. element3
  1055. element3\s
  1056. <element4>
  1057. element4
  1058. element4
  1059. element4
  1060. element4
  1061. element4
  1062. \s
  1063. <element5>
  1064. element5 element5 element5 element5 element5\s
  1065. </element5>
  1066. </element4>
  1067. </element3>
  1068. </element2>
  1069. </element1>
  1070. </element0>
  1071. </doc>
  1072. XML
  1073. end
  1074. def test_ticket_58
  1075. doc = REXML::Document.new
  1076. doc << REXML::XMLDecl.default
  1077. doc << REXML::Element.new("a")
  1078. str = ""
  1079. doc.write(str)
  1080. assert_equal("<a/>", str)
  1081. doc = REXML::Document.new
  1082. doc << REXML::XMLDecl.new("1.0", "UTF-8")
  1083. doc << REXML::Element.new("a")
  1084. str = ""
  1085. doc.write(str)
  1086. assert_equal("<?xml version='1.0' encoding='UTF-8'?><a/>", str)
  1087. end
  1088. # Incomplete tags should generate an error
  1089. def test_ticket_53
  1090. assert_raise( REXML::ParseException ) {
  1091. REXML::Document.new( "<a><b></a>" )
  1092. }
  1093. assert_raise( REXML::ParseException ) {
  1094. REXML::Document.new( "<a><b>" )
  1095. }
  1096. assert_raise( REXML::ParseException ) {
  1097. REXML::Document.new( "<a><b/>" )
  1098. }
  1099. end
  1100. def test_ticket_52
  1101. source = "<!-- this is a single line comment -->"
  1102. d = REXML::Document.new(source)
  1103. d.write(k="")
  1104. assert_equal( source, k )
  1105. source = "<a><!-- Comment --></a>"
  1106. target = "<a>\n <!-- Comment -->\n</a>"
  1107. d = REXML::Document.new(source)
  1108. REXML::Formatters::Pretty.new(4).write(d,k="")
  1109. assert_equal( target, k )
  1110. end
  1111. def test_ticket_76
  1112. src = "<div>at&t"
  1113. assert_raise( ParseException, %Q{"#{src}" is invalid XML} ) {
  1114. REXML::Document.new(src)
  1115. }
  1116. end
  1117. def test_ticket_21
  1118. src = "<foo bar=value/>"
  1119. assert_raise( ParseException, "invalid XML should be caught" ) {
  1120. Document.new(src)
  1121. }
  1122. begin
  1123. Document.new(src)
  1124. rescue
  1125. assert_match( /missing attribute quote/, $!.message )
  1126. end
  1127. end
  1128. def test_ticket_63
  1129. File.open(fixture_path("t63-1.xml")) {|f| Document.new(f) }
  1130. end
  1131. def test_ticket_75
  1132. d = File.open(fixture_path("t75.xml")) {|f| REXML::Document.new(f) }
  1133. assert_equal("tree", d.root.name)
  1134. end
  1135. def test_ticket_48_part_II
  1136. f = REXML::Formatters::Pretty.new
  1137. #- rexml sanity check (bugs in ruby 1.8.4, ruby 1.8.6)
  1138. xmldoc = Document.new("<test/>")
  1139. xmldoc << XMLDecl.new(XMLDecl::DEFAULT_VERSION, "UTF-8")
  1140. content = ['61c3a927223c3e26'].pack("H*")
  1141. content.force_encoding('UTF-8') if content.respond_to?(:force_encoding)
  1142. #- is some UTF-8 text but just to make sure my editor won't magically convert..
  1143. xmldoc.root.add_attribute('attr', content)
  1144. f.write(xmldoc,out=[])
  1145. xmldoc = REXML::Document.new(out.join)
  1146. sanity1 = xmldoc.root.attributes['attr']
  1147. f.write(xmldoc,out=[])
  1148. xmldoc = REXML::Document.new(out.join)
  1149. sanity2 = xmldoc.root.attributes['attr']
  1150. f.write(xmldoc,out=[])
  1151. assert_equal( sanity1, sanity2 )
  1152. end
  1153. def test_ticket_88
  1154. doc = REXML::Document.new("<?xml version=\"1.0\" encoding=\"shift_jis\"?>")
  1155. assert_equal("<?xml version='1.0' encoding='SHIFT_JIS'?>", doc.to_s)
  1156. doc = REXML::Document.new("<?xml version = \"1.0\" encoding = \"shift_jis\"?>")
  1157. assert_equal("<?xml version='1.0' encoding='SHIFT_JIS'?>", doc.to_s)
  1158. end
  1159. def test_ticket_85
  1160. xml = <<ENDXML
  1161. <foo>
  1162. <bar>
  1163. <bob name='jimmy'/>
  1164. </bar>
  1165. </foo>
  1166. ENDXML
  1167. yml = "<foo>
  1168. <bar>
  1169. <bob name='jimmy'/>
  1170. </bar>
  1171. </foo>"
  1172. # The pretty printer ignores all whitespace, anyway so output1 == output2
  1173. f = REXML::Formatters::Pretty.new( 2 )
  1174. d = Document.new( xml, :ignore_whitespace_nodes=>:all )
  1175. f.write( d, output1="" )
  1176. d = Document.new( xml )
  1177. f.write( d, output2="" )
  1178. # Output directives should override whitespace directives.
  1179. assert_equal( output1, output2 )
  1180. # The base case.
  1181. d = Document.new(yml)
  1182. f.write( d, output3="" )
  1183. assert_equal( output3.strip, output2.strip )
  1184. d = Document.new(yml)
  1185. f.write( d, output4="" )
  1186. assert_equal( output3.strip, output4.strip )
  1187. end
  1188. def test_ticket_91
  1189. source="<root>
  1190. <bah something='1' somethingelse='bah'>
  1191. <something>great</something>
  1192. </bah>
  1193. </root>"
  1194. expected="<root>
  1195. <bah something='1' somethingelse='bah'>
  1196. <something>great</something>
  1197. </bah>
  1198. <bah/>
  1199. </root>"
  1200. d = Document.new( source )
  1201. d.root.add_element( "bah" )
  1202. p=REXML::Formatters::Pretty.new(2)
  1203. p.compact = true # Don't add whitespace to text nodes unless necessary
  1204. p.write(d,out="")
  1205. assert_equal( expected, out )
  1206. end
  1207. def test_ticket_95
  1208. testd = REXML::Document.new "<a><b><c/><c/><c/></b></a>"
  1209. testd.write(out1="")
  1210. testd.elements["//c[2]"].xpath
  1211. testd.write(out2="")
  1212. assert_equal(out1,out2)
  1213. end
  1214. def test_ticket_102
  1215. doc = REXML::Document.new '<doc xmlns="ns"><item name="foo"/></doc>'
  1216. assert_equal( "foo", doc.root.elements["item"].attribute("name","ns").to_s )
  1217. assert_equal( "item", doc.root.elements["item[@name='foo']"].name )
  1218. end
  1219. def test_ticket_14
  1220. # Per .2.5 Node Tests of XPath spec
  1221. assert_raise( REXML::UndefinedNamespaceException,
  1222. %Q{Should have gotten an Undefined Namespace error} ) {
  1223. Document.new("<a><n:b/></a>")
  1224. }
  1225. end
  1226. # 5.7 Text Nodes
  1227. # Character data is grouped into text nodes. As much character data as
  1228. # possible is grouped into each text node: a text node never has an
  1229. # immediately following or preceding sibling that is a text node. The
  1230. # string-value of a text node is the character data. A text node always has
  1231. # at least one character of data.
  1232. def test_ticket_105
  1233. d = Document.new("<a/>")
  1234. d.root.add_text( "a" )
  1235. d.root.add_text( "b" )
  1236. assert_equal( 1, d.root.children.size )
  1237. end
  1238. # phantom namespace same as default namespace
  1239. def test_ticket_121
  1240. doc = REXML::Document.new(
  1241. '<doc xmlns="ns" xmlns:phantom="ns"><item name="foo">text</item></doc>'
  1242. )
  1243. assert_equal 'text', doc.text( "/doc/item[@name='foo']" )
  1244. assert_equal "name='foo'",
  1245. doc.root.elements["item"].attribute("name", "ns").inspect
  1246. assert_equal "<item name='foo'>text</item>",
  1247. doc.root.elements["item[@name='foo']"].to_s
  1248. end
  1249. def test_ticket_135
  1250. bean_element = REXML::Element.new("bean")
  1251. textToAdd = "(&#38;(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))"
  1252. bean_element.add_element("prop", {"key"=> "filter"}).add_text(textToAdd)
  1253. doc = REXML::Document.new
  1254. doc.add_element(bean_element)
  1255. REXML::Formatters::Pretty.new(3).write( doc, out = "" )
  1256. assert_equal "<bean>\n <prop key='filter'>\n (&amp;#38;(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))\n </prop>\n</bean>", out
  1257. end
  1258. def test_ticket_138
  1259. doc = REXML::Document.new(
  1260. '<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" ' +
  1261. 'inkscape:version="0.44" version="1.0"/>'
  1262. )
  1263. expected = {
  1264. "inkscape" => attribute("xmlns:inkscape",
  1265. "http://www.inkscape.org/namespaces/inkscape"),
  1266. "version" => {
  1267. "inkscape" => attribute("inkscape:version", "0.44"),
  1268. "" => attribute("version", "1.0"),
  1269. },
  1270. }
  1271. assert_equal(expected, doc.root.attributes)
  1272. assert_equal(expected, REXML::Document.new(doc.root.to_s).root.attributes)
  1273. end
  1274. def test_empty_doc
  1275. assert(REXML::Document.new('').children.empty?)
  1276. end
  1277. private
  1278. def attribute(name, value)
  1279. REXML::Attribute.new(name, value)
  1280. end
  1281. end
  1282. end