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