mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
0d1abb904e
See https://github.com/ruby/rexml/blob/master/NEWS.md for change summary. Changes for spec/ has been reported: https://github.com/ruby/spec/pull/639 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66458 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1469 lines
44 KiB
Ruby
1469 lines
44 KiB
Ruby
# coding: binary
|
|
# frozen_string_literal: false
|
|
|
|
require_relative "rexml_test_utils"
|
|
|
|
require "rexml/document"
|
|
require "rexml/parseexception"
|
|
require "rexml/output"
|
|
require "rexml/source"
|
|
require "rexml/formatters/pretty"
|
|
require "rexml/undefinednamespaceexception"
|
|
|
|
require_relative "listener"
|
|
|
|
module REXMLTests
|
|
class Tester < Test::Unit::TestCase
|
|
include REXMLTestUtils
|
|
include REXML
|
|
def setup
|
|
@xsa_source = <<-EOL
|
|
<?xml version="1.0"?>
|
|
<?xsl stylesheet="blah.xsl"?>
|
|
<!-- The first line tests the XMLDecl, the second tests PI.
|
|
The next line tests DocType. This line tests comments. -->
|
|
<!DOCTYPE xsa PUBLIC
|
|
"-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
|
|
"http://www.garshol.priv.no/download/xsa/xsa.dtd">
|
|
|
|
<xsa>
|
|
<vendor id="blah">
|
|
<name>Lars Marius Garshol</name>
|
|
<email>larsga@garshol.priv.no</email>
|
|
<url>http://www.stud.ifi.uio.no/~lmariusg/</url>
|
|
</vendor>
|
|
</xsa>
|
|
EOL
|
|
end
|
|
|
|
def test_bad_markup
|
|
[
|
|
"<pkg='version'> foo </pkg>",
|
|
'<0/>',
|
|
'<a>&</a>',
|
|
'<a>&a</a>',
|
|
# '<a>&a;</a>', # FIXME
|
|
'<a a="<"/>',
|
|
'<a 3="<"/>',
|
|
'<a a="1" a="2"/>',
|
|
'<a><!-- -- --></a>',
|
|
'<a><!-- ---></a>',
|
|
'<a>�</a>',
|
|
'<a>�</a>',
|
|
"<a a='�' />",
|
|
"<a>\f</a>",
|
|
"<a a='\f' />",
|
|
"<a>\000</a>",
|
|
# FIXME '<a' + [65535].pack('U') + ' />',
|
|
'<a></a>',
|
|
'<a></a>',
|
|
# FIXME '<a' + [0x0371].pack('U') + ' />',
|
|
# FIXME '<a a' + [0x0371].pack('U') + '="" />',
|
|
].each do |src|
|
|
assert_raise( ParseException, %Q{Parse #{src.inspect} should have failed!} ) do
|
|
Document.new(src)
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_attribute
|
|
# Testing constructors
|
|
#a = Attribute.new "hello", "dolly"
|
|
#b = Attribute.new a
|
|
#d = Document.new( "<a hello='dolly' href='blah'/>" )
|
|
#c = d[0].attributes.get_attribute( "hello" )
|
|
|
|
#assert_equal a, b
|
|
#for attr in [ a, b, c]
|
|
# assert_equal "hello", attr.name
|
|
# assert_equal "dolly", attr.value
|
|
#end
|
|
|
|
# This because of a reported bug in attribute handling in 1.0a8
|
|
source = '<a att="A">blah</a>'
|
|
doc = Document.new source
|
|
doc.elements.each do |a|
|
|
a.attributes['att'] << 'B'
|
|
assert_equal "AB", a.attributes['att']
|
|
a.attributes['att'] = 'C'
|
|
assert_equal "C", a.attributes['att']
|
|
end
|
|
|
|
# Bryan Murphy <murphybryanp@yahoo.com>
|
|
text = "this is a {target[@name='test']/@value} test"
|
|
source = <<-EOL
|
|
<?xml version="1.0"?>
|
|
<doc search="#{text}"/>
|
|
EOL
|
|
|
|
xml = Document.new source
|
|
value = xml.root.attributes["search"]
|
|
assert_equal text, value.to_s
|
|
|
|
e = Element.new "test"
|
|
e.add_attributes({ "name1" => "test1", "name4" => "test4" })
|
|
e.add_attributes([["name3","test3"], ["name2","test2"]])
|
|
assert_equal "test1", e.attributes["name1"]
|
|
assert_equal "test2", e.attributes["name2"]
|
|
assert_equal "test3", e.attributes["name3"]
|
|
assert_equal "test4", e.attributes["name4"]
|
|
|
|
# ensure that the attributes come out in sorted order
|
|
assert_equal %w(<test
|
|
name1='test1'
|
|
name2='test2'
|
|
name3='test3'
|
|
name4='test4'/>).join(' '), e.to_s
|
|
end
|
|
|
|
def test_cdata
|
|
test = "The quick brown fox jumped
|
|
& < & < \" '
|
|
over the lazy dog."
|
|
|
|
source = "<a><![CDATA[#{test}]]></a>"
|
|
d = REXML::Document.new( source )
|
|
|
|
# Test constructors
|
|
cdata = d[0][0]
|
|
assert_equal test, cdata.value
|
|
end
|
|
|
|
def test_comment
|
|
string = "This is a new comment!"
|
|
source = "<!--#{string}-->"
|
|
comment = Comment.new string
|
|
REXML::Formatters::Default.new.write( comment, out = "" )
|
|
assert_equal(source, out)
|
|
|
|
comment2 = Comment.new comment
|
|
assert_equal(comment, comment2)
|
|
|
|
assert_raise(ParseException) {
|
|
REXML::Document.new("<d><!- foo --></d>")
|
|
}
|
|
assert_raise(ParseException) {
|
|
REXML::Document.new("<d><!-- foo -></d>")
|
|
}
|
|
end
|
|
|
|
def test_whitespace
|
|
doc = Document.new "<root-element><first-element/></root-element>"
|
|
assert_equal 1, doc.root.size
|
|
assert_equal 1, doc.root.elements.size
|
|
doc = Document.new "<root-element>
|
|
<first-element/>
|
|
</root-element>"
|
|
assert_equal 3, doc.root.size
|
|
assert_equal 1, doc.root.elements.size
|
|
|
|
text = " This is text
|
|
with a lot of whitespace "
|
|
source = "<a>#{text}<b>#{text}</b><c>#{text}</c>#{text}</a>"
|
|
|
|
doc = Document.new( source, {
|
|
:respect_whitespace => %w{ a c }
|
|
} )
|
|
assert_equal text, doc.elements["//c"].text
|
|
string = ""
|
|
doc.root.each { |n| string << n.to_s if n.kind_of? Text }
|
|
assert_equal text+text, string
|
|
|
|
string =" lots of blank
|
|
space"
|
|
doc.root.add_element("d").add_element("c").text = string
|
|
doc.root.add_element("e").text = string
|
|
assert_equal string, doc.elements["/a/d/c"].text
|
|
assert string != doc.elements["/a/e"].text, "Text wasn't properly compressed"
|
|
|
|
doc = Document.new source, { :respect_whitespace => :all }
|
|
doc.root.add_element("d").text = string
|
|
assert_equal text, doc.root.text
|
|
nxt = ""
|
|
doc.root.each { |n| nxt << n.to_s if n.kind_of? Text }
|
|
assert_equal text+text, nxt
|
|
assert_equal text, doc.root.elements["b"].text
|
|
assert_equal text, doc.root.elements["c"].text
|
|
assert_equal string, doc.root.elements["d"].text
|
|
end
|
|
|
|
# This isn't complete. We need to check declarations and comments
|
|
def test_doctype
|
|
string = "something"
|
|
correct = "<!DOCTYPE something>"
|
|
doc = DocType.new(string)
|
|
assert_equal(string, doc.name)
|
|
doc.write(out="")
|
|
assert_equal(correct, out)
|
|
|
|
doc2 = DocType.new(doc)
|
|
assert_equal(doc.name, doc2.name)
|
|
assert_equal(doc.external_id, doc2.external_id)
|
|
|
|
correct = '<!DOCTYPE xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML" "http://www.garshol.priv.no/download/xsa/xsa.dtd">'
|
|
|
|
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/>'
|
|
doc = Document.new( one_line_source )
|
|
doc = doc[0]
|
|
assert(doc)
|
|
doc.write(test="")
|
|
assert_equal(correct, test)
|
|
|
|
multi_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/>'
|
|
d = Document.new( multi_line_source )
|
|
doc = d[0]
|
|
assert(doc)
|
|
doc.write(test="")
|
|
assert_equal(correct, test)
|
|
|
|
odd_space_source = ' <!DOCTYPE
|
|
xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
|
|
"http://www.garshol.priv.no/download/xsa/xsa.dtd"> <a/>'
|
|
d = Document.new( odd_space_source )
|
|
dt = d.doctype
|
|
dt.write(test="")
|
|
assert_equal(correct, test)
|
|
|
|
# OK, the BIG doctype test, numba wun
|
|
doc = File.open(fixture_path("doctype_test.xml")) do |docin|
|
|
Document.new(docin)
|
|
end
|
|
doc.write(test="")
|
|
assert_equal(31, doc.doctype.size)
|
|
end
|
|
|
|
def test_document
|
|
# Testing cloning
|
|
source = "<element/>"
|
|
doc = Document.new source
|
|
|
|
# Testing Root
|
|
assert_equal doc.root.name.to_s, "element"
|
|
|
|
# Testing String source
|
|
source = @xsa_source
|
|
doc = Document.new source
|
|
assert_instance_of XMLDecl, doc.xml_decl
|
|
assert_instance_of DocType, doc.doctype
|
|
assert_equal doc.version, "1.0"
|
|
|
|
doc = File.open(fixture_path("dash.xml")) {|s| Document.new s }
|
|
assert_equal "content-2", doc.elements["//content-2"].name
|
|
end
|
|
|
|
def test_instruction
|
|
target = "use"
|
|
content = "ruby"
|
|
source = "<?#{target} #{content}?>"
|
|
|
|
instruction = Instruction.new target, content
|
|
instruction2 = Instruction.new instruction
|
|
assert_equal(instruction, instruction2)
|
|
REXML::Formatters::Default.new.write( instruction, out = "" )
|
|
assert_equal(source, out)
|
|
|
|
d = Document.new( source )
|
|
instruction2 = d[0]
|
|
assert_equal(instruction.to_s, instruction2.to_s)
|
|
|
|
assert_raise(ParseException) {
|
|
REXML::Document.new("<d><?foo bar></d>")
|
|
}
|
|
end
|
|
|
|
def test_parent
|
|
parent = Parent.new
|
|
begin
|
|
parent << "Something"
|
|
rescue Exception
|
|
parent << Comment.new("Some comment")
|
|
assert parent.size == 1, "size of parent should be 1"
|
|
else
|
|
assert_fail "should have gotten an exception trying to add a "+ "String to a Parent"
|
|
end
|
|
|
|
source = "<a><one/><three/><five/></a>"
|
|
doc = Document.new source
|
|
three = doc.root.elements["three"]
|
|
doc.root.insert_before( three, Element.new("two") )
|
|
nxt = doc.root.elements["one"]
|
|
string = ""
|
|
while nxt
|
|
string << nxt.name
|
|
nxt = nxt.next_sibling
|
|
end
|
|
assert_equal "onetwothreefive", string
|
|
|
|
|
|
doc.root.insert_after( three, Element.new("four") )
|
|
string = ""
|
|
doc.root.each { |element| string << element.name }
|
|
assert_equal "onetwothreefourfive", string
|
|
|
|
string = ""
|
|
nxt = doc.root.elements["five"]
|
|
while nxt
|
|
string << nxt.name
|
|
nxt = nxt.previous_sibling
|
|
end
|
|
assert_equal "fivefourthreetwoone", string
|
|
|
|
doc.insert_after "//two", Element.new("two-and-half")
|
|
string = doc.root.elements.collect {|x| x.name}.join
|
|
assert_equal "onetwotwo-and-halfthreefourfive", string
|
|
doc.elements["/a/five"].insert_before "../four", Element.new("three-and-half")
|
|
string = doc.root.elements.collect {|x| x.name}.join
|
|
assert_equal "onetwotwo-and-halfthreethree-and-halffourfive", string
|
|
|
|
doc.elements["/a/five"].previous_sibling = Element.new("four-and-half")
|
|
string = doc.root.elements.collect {|x| x.name}.join
|
|
assert_equal "onetwotwo-and-halfthreethree-and-halffourfour-and-halffive", string
|
|
doc.elements["/a/one"].next_sibling = Element.new("one-and-half")
|
|
string = doc.root.elements.collect {|x| x.name}.join
|
|
assert_equal "oneone-and-halftwotwo-and-halfthreethree-and-halffourfour-and-halffive", string
|
|
|
|
doc = Document.new "<a><one/><three/></a>"
|
|
doc.root[1,0] = Element.new "two"
|
|
string = ""
|
|
doc.root.each { |el| string << el.name }
|
|
assert_equal "onetwothree", string
|
|
end
|
|
|
|
# The Source classes are tested extensively throughout the test suite
|
|
def test_source
|
|
# Testing string source
|
|
source = @xsa_source
|
|
doc = Document.new source
|
|
assert_equal doc.root.name.to_s, "xsa"
|
|
|
|
# Testing IO source
|
|
doc = File.open(fixture_path("project.xml")) {|f| Document.new f }
|
|
assert_equal doc.root.name.to_s, "Project"
|
|
end
|
|
|
|
def test_text
|
|
f = REXML::Formatters::Default.new
|
|
string = "Some text"
|
|
text = Text.new(string)
|
|
assert_equal(string, text.to_s)
|
|
text2 = Text.new(text)
|
|
assert_equal(text, text2)
|
|
#testing substitution
|
|
string = "0 < ( 1 & 1 )"
|
|
correct = "0 < ( 1 & 1 )"
|
|
text = Text.new(string, true)
|
|
f.write(text,out="")
|
|
assert_equal(correct, out)
|
|
|
|
string = "Cats & dogs"
|
|
text = Text.new(string, false, nil, true)
|
|
assert_equal(string, text.to_s)
|
|
|
|
string2 = "<a>#{string}</a>"
|
|
doc = Document.new( string2, {
|
|
:raw => %w{ a b }
|
|
} )
|
|
f.write(doc,out="")
|
|
assert_equal(string2, out)
|
|
b = doc.root.add_element( "b" )
|
|
b.text = string
|
|
assert_equal(string, b.get_text.to_s)
|
|
|
|
c = doc.root.add_element("c")
|
|
c.text = string
|
|
assert_equal("Cats &amp; dogs", c.get_text.to_s)
|
|
|
|
# test all
|
|
string = "<a>&<b><</b><c>><d>"</d></c></a>"
|
|
doc = Document.new(string, { :raw => :all })
|
|
assert_equal( "&", doc.elements["/a"][0].to_s )
|
|
assert_equal( "&", doc.elements["/a"].text )
|
|
assert_equal( "<", doc.elements["/a/b"][0].to_s )
|
|
assert_equal( "<", doc.elements["/a/b"].text )
|
|
assert_equal( ">", doc.elements["/a/c"][0].to_s )
|
|
assert_equal( ">", doc.elements["/a/c"].text )
|
|
assert_equal( '"', doc.elements["//d"][0].to_s )
|
|
assert_equal( '"', doc.elements["//d"].text )
|
|
|
|
# test some other stuff
|
|
doc = Document.new('<a><b/></a>')
|
|
doc.root.text = 'Sean'
|
|
assert_equal( '<a><b/>Sean</a>', doc.to_s )
|
|
doc.root.text = 'Elliott'
|
|
assert_equal( '<a><b/>Elliott</a>', doc.to_s )
|
|
doc.root.add_element( 'c' )
|
|
assert_equal( '<a><b/>Elliott<c/></a>', doc.to_s )
|
|
doc.root.text = 'Russell'
|
|
assert_equal( '<a><b/>Russell<c/></a>', doc.to_s )
|
|
doc.root.text = nil
|
|
assert_equal( '<a><b/><c/></a>', doc.to_s )
|
|
end
|
|
|
|
def test_text_frozen
|
|
string = "Frozen".freeze
|
|
text = Text.new(string)
|
|
assert_equal(string, text.to_s)
|
|
end
|
|
|
|
def test_xmldecl
|
|
source = "<?xml version='1.0'?>"
|
|
# test args
|
|
# test no args
|
|
decl2 = XMLDecl.new
|
|
assert_equal source, decl2.to_s
|
|
# test XMLDecl
|
|
decl2 = XMLDecl.new "1.0"
|
|
assert_equal source, decl2.to_s
|
|
end
|
|
|
|
def test_xmldecl_utf_16be_encoding_name
|
|
assert_equal("<?xml version='1.0' encoding='UTF-16'?>",
|
|
XMLDecl.new("1.0", "UTF-16").to_s)
|
|
end
|
|
|
|
def each_test( element, xpath, num_children )
|
|
count = 0
|
|
element.each_element( xpath ) { |child|
|
|
count += 1
|
|
yield child if block_given?
|
|
}
|
|
assert_equal num_children, count
|
|
end
|
|
|
|
# This is the biggest test, as the number of permutations of xpath are
|
|
# enormous.
|
|
def test_element_access
|
|
# Testing each_element
|
|
doc = File.open(fixture_path("project.xml")) {|f| Document.new f }
|
|
|
|
each_test( doc, "/", 1 ) { |child|
|
|
assert_equal doc.name, child.name
|
|
}
|
|
each_test(doc, ".", 1) { |child| assert_equal doc, child }
|
|
each_test(doc.root, "..", 1) { |child| assert_equal doc, child }
|
|
each_test(doc.root, "*", 5)
|
|
each_test(doc, "Project/Datasets", 1) { |child|
|
|
assert_equal "Datasets", child.name
|
|
}
|
|
each_test(doc, "Project/Datasets/link", 2 )
|
|
each_test(doc.root, "/Project/Description", 1) {|child|
|
|
assert_equal "Description", child.name
|
|
}
|
|
each_test(doc.root, "./Description",1 ) { |child|
|
|
assert_equal "Description",child.name
|
|
}
|
|
each_test(doc.root, "../Project",1 ) { |child|
|
|
assert_equal doc.root, child
|
|
}
|
|
#each_test(doc,".../link",2) {|child| assert_equal "link",child.name.to_s}
|
|
|
|
# test get_element
|
|
first = doc.elements[ "Project" ]
|
|
assert_equal doc.root, first
|
|
second = doc.elements[ "Project" ].elements[1]
|
|
third = doc.elements[ "Project/Creator" ]
|
|
assert_equal second, third
|
|
fourth = doc.elements[ "Project/Datasets/link[@idref='18']" ]
|
|
assert_equal "Test data 1", fourth.attributes["name"]
|
|
|
|
# Testing each_predicate
|
|
each_test( doc, "Project/Datasets/link[@idref='18']", 1 ) { |child|
|
|
assert_equal "Test data 1", child.attributes["name"]
|
|
}
|
|
|
|
# testing next/previous_element
|
|
creator = doc.elements["//Creator"]
|
|
lm = creator.next_element
|
|
assert_equal "LastModifier", lm.name
|
|
assert_equal "Creator", lm.previous_element.name
|
|
end
|
|
|
|
def test_child
|
|
sean = Element.new "Sean"
|
|
rubbell = Element.new "Rubbell"
|
|
elliott = sean.add_element "Elliott"
|
|
sean << rubbell
|
|
assert_equal elliott, rubbell.previous_sibling
|
|
assert_equal rubbell, elliott.next_sibling
|
|
|
|
russell = Element.new "Russell"
|
|
rubbell.replace_with russell
|
|
assert_equal elliott, russell.previous_sibling
|
|
assert_equal russell, elliott.next_sibling
|
|
|
|
assert_nil russell.document
|
|
assert_equal sean, russell.root
|
|
end
|
|
|
|
# Most of this class is tested elsewhere. Here are the methods which
|
|
# aren't used in any other class
|
|
def test_element
|
|
sean = Element.new "Sean"
|
|
string = "1) He's a great guy!"
|
|
sean.text = string
|
|
russell = Element.new "Russell"
|
|
sean << russell
|
|
|
|
russell.attributes["email"] = "ser@germane-software.com"
|
|
assert_equal russell.attributes["email"], "ser@germane-software.com"
|
|
russell.attributes["webpage"] = "http://www.germane-software.com/~ser"
|
|
|
|
assert sean.has_text?, "element should have text"
|
|
assert_equal sean.text, string
|
|
assert sean.has_elements?, "element should have one element"
|
|
string = "2) What a stud!"
|
|
sean.add_text string
|
|
sean.text = "3) Super programmer!"
|
|
sean.text = nil
|
|
assert sean.has_text?, "element should still have text"
|
|
assert_equal sean.text, string
|
|
|
|
russell.delete_attribute "email"
|
|
assert_nil russell.attributes["email"]
|
|
russell.attributes.delete "webpage"
|
|
assert !russell.has_attributes?, "element should have no attributes"
|
|
end
|
|
|
|
def test_no_format
|
|
source = "<a><b><c>blah</c><d/></b></a>"
|
|
out = ""
|
|
doc = Document.new( source )
|
|
doc.write(out)
|
|
assert_equal(source, out)
|
|
end
|
|
|
|
def test_namespace
|
|
source = <<-EOF
|
|
<x xmlns:foo="http://www.bar.com/schema">
|
|
</x>
|
|
EOF
|
|
doc = Document.new(source)
|
|
assert_equal("http://www.bar.com/schema", doc.root.namespace( "foo" ))
|
|
source = <<-EOF
|
|
<!-- bar namespace is "someuri" -->
|
|
<foo:bar xmlns="default" xmlns:foo="someuri">
|
|
<!-- a namespace is "default" -->
|
|
<a/>
|
|
<!-- foo:b namespace is "someuri" -->
|
|
<foo:b>
|
|
<!-- c namespace is "default" -->
|
|
<c/>
|
|
</foo:b>
|
|
<!-- d namespace is "notdefault" -->
|
|
<d xmlns="notdefault">
|
|
<!-- e namespace is "notdefault" -->
|
|
<e/>
|
|
<f xmlns="">
|
|
<g/>
|
|
</f>
|
|
</d>
|
|
</foo:bar>
|
|
EOF
|
|
doc = Document.new source
|
|
assert_equal "someuri", doc.root.namespace
|
|
assert_equal "default", doc.root.elements[1].namespace
|
|
assert_equal "someuri", doc.root.elements[2].namespace
|
|
assert_equal "notdefault", doc.root.elements[ 3 ].namespace
|
|
|
|
# Testing namespaces in attributes
|
|
source = <<-EOF
|
|
<a xmlns:b="uri">
|
|
<b b:a="x" a="y"/>
|
|
<c xmlns="foo">
|
|
</c>
|
|
</a>
|
|
EOF
|
|
doc = Document.new source
|
|
b = doc.root.elements["b"]
|
|
assert_equal "x", b.attributes["b:a"]
|
|
assert_equal "y", b.attributes["a"]
|
|
|
|
doc = Document.new
|
|
doc.add_element "sean:blah"
|
|
doc.root.text = "Some text"
|
|
out = ""
|
|
doc.write(out)
|
|
assert_equal "<sean:blah>Some text</sean:blah>", out
|
|
end
|
|
|
|
|
|
def test_add_namespace
|
|
e = Element.new 'a'
|
|
e.add_namespace 'someuri'
|
|
e.add_namespace 'foo', 'otheruri'
|
|
e.add_namespace 'xmlns:bar', 'thirduri'
|
|
assert_equal 'someuri', e.attributes['xmlns']
|
|
assert_equal 'otheruri', e.attributes['xmlns:foo']
|
|
assert_equal 'thirduri', e.attributes['xmlns:bar']
|
|
end
|
|
|
|
|
|
def test_big_documentation
|
|
d = File.open(fixture_path("documentation.xml")) {|f| Document.new f }
|
|
assert_equal "Sean Russell", d.elements["documentation/head/author"].text.tr("\n\t", " ").squeeze(" ")
|
|
out = ""
|
|
d.write out
|
|
end
|
|
|
|
def test_tutorial
|
|
doc = File.open(fixture_path("tutorial.xml")) {|f| Document.new f }
|
|
out = ""
|
|
doc.write out
|
|
end
|
|
|
|
def test_stream
|
|
c = Listener.new
|
|
File.open(fixture_path("documentation.xml")) do |f|
|
|
Document.parse_stream( f, c )
|
|
end
|
|
assert(c.ts, "Stream parsing apparently didn't parse the whole file")
|
|
assert(c.te, "Stream parsing dropped end tag for documentation")
|
|
|
|
Document.parse_stream("<a.b> <c/> </a.b>", c)
|
|
|
|
Document.parse_stream("<a><>&</a>", c)
|
|
assert_equal('<>&', c.normalize)
|
|
end
|
|
|
|
def test_line
|
|
f = File.new(fixture_path("bad.xml"))
|
|
Document.new f
|
|
assert_fail "There should have been an error"
|
|
rescue Exception
|
|
# We should get here
|
|
assert($!.line == 5, "Should have been an error on line 5, "+
|
|
"but was reported as being on line #{$!.line}" )
|
|
ensure
|
|
f.close if f
|
|
end
|
|
|
|
def test_substitution
|
|
val = "a'b\"c"
|
|
el = Element.new("a")
|
|
el.attributes["x"] = val
|
|
REXML::Formatters::Default.new.write(el, out="")
|
|
|
|
nel = Document.new( out)
|
|
assert_equal( val, nel.root.attributes["x"] )
|
|
end
|
|
|
|
def test_exception
|
|
source = SourceFactory.create_from "<a/>"
|
|
p = ParseException.new( "dummy message", source )
|
|
begin
|
|
raise "dummy"
|
|
rescue Exception
|
|
p.continued_exception = $!
|
|
end
|
|
end
|
|
|
|
def test_bad_content
|
|
in_gt = '<root-el>content>content</root-el>'
|
|
in_lt = '<root-el>content<content</root-el>'
|
|
|
|
# This is OK
|
|
tree_gt = Document.new in_gt
|
|
assert_equal "content>content", tree_gt.elements[1].text
|
|
# This isn't
|
|
begin
|
|
Document.new in_lt
|
|
assert_fail "Should have gotten a parse error"
|
|
rescue ParseException
|
|
end
|
|
end
|
|
|
|
def test_iso_8859_1_output_function
|
|
out = ""
|
|
output = Output.new( out )
|
|
koln_iso_8859_1 = "K\xF6ln"
|
|
koln_utf8 = "K\xc3\xb6ln"
|
|
source = Source.new( koln_iso_8859_1, 'iso-8859-1' )
|
|
results = source.scan(/.*/)[0]
|
|
koln_utf8.force_encoding('UTF-8') if koln_utf8.respond_to?(:force_encoding)
|
|
assert_equal koln_utf8, results
|
|
output << results
|
|
if koln_iso_8859_1.respond_to?(:force_encoding)
|
|
koln_iso_8859_1.force_encoding('ISO-8859-1')
|
|
end
|
|
assert_equal koln_iso_8859_1, out
|
|
end
|
|
|
|
def test_attributes_each
|
|
doc = Document.new("<a xmlns:a='foo'><b x='1' y='2' z='3' a:x='4'/></a>")
|
|
count = 0
|
|
doc.root.elements[1].attributes.each {|k,v| count += 1 }
|
|
assert_equal 4, count
|
|
end
|
|
|
|
def test_delete_namespace
|
|
doc = Document.new "<a xmlns='1' xmlns:x='2'/>"
|
|
doc.root.delete_namespace
|
|
doc.root.delete_namespace 'x'
|
|
assert_equal "<a/>", doc.to_s
|
|
end
|
|
|
|
def test_each_element_with_attribute
|
|
doc = Document.new "<a><b id='1'/><c id='2'/><d id='1'/><e/></a>"
|
|
arry = []
|
|
block = proc { |e|
|
|
assert arry.include?(e.name)
|
|
arry.delete e.name
|
|
}
|
|
# Yields b, c, d
|
|
arry = %w{b c d}
|
|
doc.root.each_element_with_attribute( 'id', &block )
|
|
assert_equal 0, arry.size
|
|
# Yields b, d
|
|
arry = %w{b d}
|
|
doc.root.each_element_with_attribute( 'id', '1', &block )
|
|
assert_equal 0, arry.size
|
|
# Yields b
|
|
arry = ['b']
|
|
doc.root.each_element_with_attribute( 'id', '1', 1, &block )
|
|
assert_equal 0, arry.size
|
|
# Yields d
|
|
arry = ['d']
|
|
doc.root.each_element_with_attribute( 'id', '1', 0, 'd', &block )
|
|
assert_equal 0, arry.size
|
|
end
|
|
def test_each_element_with_text
|
|
doc = Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
|
|
arry = []
|
|
block = proc { |e|
|
|
assert arry.include?(e.name)
|
|
arry.delete e.name
|
|
}
|
|
# Yields b, c, d
|
|
arry = %w{b c d}
|
|
doc.root.each_element_with_text(&block)
|
|
assert_equal 0, arry.size
|
|
# Yields b, d
|
|
arry = %w{b c}
|
|
doc.root.each_element_with_text( 'b', &block )
|
|
assert_equal 0, arry.size
|
|
# Yields b
|
|
arry = ['b']
|
|
doc.root.each_element_with_text( 'b', 1, &block )
|
|
assert_equal 0, arry.size
|
|
# Yields d
|
|
arry = ['d']
|
|
doc.root.each_element_with_text( nil, 0, 'd', &block )
|
|
assert_equal 0, arry.size
|
|
end
|
|
|
|
def test_element_parse_stream
|
|
s = Source.new( "<a>some text</a>" )
|
|
l = Listener.new
|
|
class << l
|
|
def tag_start name, attributes
|
|
raise "Didn't find proper tag name" unless 'a'==name
|
|
end
|
|
end
|
|
|
|
Document::parse_stream(s, l)
|
|
end
|
|
|
|
def test_deep_clone
|
|
a = Document.new( '<?xml version="1"?><a x="y"><b>text</b>text<c><d><e>text</e></d></c></a>' )
|
|
b = a.deep_clone
|
|
assert_equal a.to_s, b.to_s
|
|
|
|
a = Document.new( '<a>some < text <b> more > text </b> > </a>' )
|
|
b = a.deep_clone
|
|
assert_equal a.to_s, b.to_s
|
|
c = Document.new( b.to_s )
|
|
assert_equal a.to_s, c.to_s
|
|
end
|
|
|
|
def test_whitespace_before_root
|
|
a = <<EOL
|
|
<?xml version='1.0'?>
|
|
<blo>
|
|
<wak>
|
|
</wak>
|
|
</blo>
|
|
EOL
|
|
d = Document.new(a)
|
|
b = ""
|
|
d.write( b )
|
|
assert_equal a,b
|
|
end
|
|
|
|
def test_entities
|
|
a = Document.new( '<a>eeü</a>' )
|
|
assert_equal('eeü'.force_encoding("UTF-8"), a.root.text)
|
|
end
|
|
|
|
def test_element_decl
|
|
element_decl = Source.new("<!DOCTYPE foo [
|
|
<!ELEMENT bar (#PCDATA)>
|
|
]>")
|
|
doc = Document.new( element_decl )
|
|
d = doc[0]
|
|
assert_equal("<!ELEMENT bar (#PCDATA)>", d.to_s.split(/\n/)[1].strip)
|
|
end
|
|
|
|
def test_attlist_decl
|
|
doc = Document.new <<-EOL
|
|
<!DOCTYPE blah [
|
|
<!ATTLIST blah
|
|
xmlns CDATA "foo">
|
|
<!ATTLIST a
|
|
bar CDATA "gobble"
|
|
xmlns:one CDATA "two"
|
|
>
|
|
]>
|
|
<a xmlns:three='xxx' three='yyy'><one:b/><three:c/></a>
|
|
EOL
|
|
assert_equal 'gobble', doc.root.attributes['bar']
|
|
assert_equal 'xxx', doc.root.elements[2].namespace
|
|
assert_equal 'two', doc.root.elements[1].namespace
|
|
assert_equal 'foo', doc.root.namespace
|
|
|
|
doc = Document.new <<-EOL
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE schema SYSTEM "XMLSchema.dtd" [
|
|
<!ENTITY % p ''>
|
|
<!ENTITY % s ''>
|
|
<!ATTLIST schema
|
|
xmlns:svg CDATA #FIXED "http://www.w3.org/2000/svg"
|
|
xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"
|
|
xmlns:xml CDATA #FIXED "http://www.w3.org/XML/1998/namespace"
|
|
>]>
|
|
<schema/>
|
|
EOL
|
|
prefixes = doc.root.prefixes.sort
|
|
correct = ['svg', 'xlink', 'xml']
|
|
assert_equal correct, prefixes
|
|
end
|
|
|
|
def test_attlist_write
|
|
doc = File.open(fixture_path("foo.xml")) {|file| Document.new file }
|
|
out = ''
|
|
doc.write(out)
|
|
end
|
|
|
|
def test_more_namespaces
|
|
assert_raise( REXML::UndefinedNamespaceException,
|
|
%Q{Should have gotten an Undefined Namespace error} ) {
|
|
Document.new("<r><p><n:c/></p></r>")
|
|
}
|
|
doc2 = Document.new("<r xmlns:n='1'><p><n:c/></p></r>")
|
|
es = XPath.match(doc2, '//c')
|
|
assert_equal 0, es.size
|
|
es = XPath.match(doc2, '//n:c')
|
|
assert_equal 1, es.size
|
|
doc2.root.add_namespace('m', '2')
|
|
doc2.root.add_element("m:o")
|
|
es = XPath.match(doc2, './/o')
|
|
assert_equal 0, es.size
|
|
es = XPath.match(doc2, '//n:c')
|
|
assert_equal 1, es.size
|
|
end
|
|
|
|
def test_ticket_51
|
|
doc = REXML::Document.new <<-EOL
|
|
<test xmlns='1' xmlns:x='1'>
|
|
<a>X</a>
|
|
<x:a>Y</x:a>
|
|
|
|
<b xmlns='2'>
|
|
<a>Z</a>
|
|
</b>
|
|
</test>
|
|
EOL
|
|
|
|
# The most common case. People not caring about the namespaces much.
|
|
assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()" ).join )
|
|
assert_equal( "XY", XPath.match( doc, "/*:test/x:a/text()" ).join )
|
|
# Surprising? I don't think so, if you believe my definition of the "common case"
|
|
assert_equal( "XYZ", XPath.match( doc, "//*:a/text()" ).join )
|
|
|
|
# These are the uncommon cases. Namespaces are actually important, so we define our own
|
|
# mappings, and pass them in.
|
|
assert_equal( "XY", XPath.match( doc, "/f:test/f:a/text()", { "f" => "1" } ).join )
|
|
# The namespaces are defined, and override the original mappings
|
|
assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()", { "f" => "1" } ).join )
|
|
assert_equal( "", XPath.match( doc, "/x:test/x:a/text()", { "f" => "1" } ).join )
|
|
assert_equal( "XYZ", XPath.match( doc, "//*:a/text()", { "f" => "1" } ).join )
|
|
end
|
|
|
|
def test_processing_instruction
|
|
d = Document.new("<a><?foo bar?><?foo2 bar2?><b><?foo3 bar3?></b><?foo4 bar4?></a>")
|
|
assert_equal 4, XPath.match(d, '//processing-instruction()' ).size
|
|
match = XPath.match(d, "//processing-instruction('foo3')" )
|
|
assert_equal 1, match.size
|
|
assert_equal 'bar3', match[0].content
|
|
end
|
|
|
|
def test_oses_with_bad_EOLs
|
|
Document.new("\n\n\n<?xml version='1.0'?>\n\n\n<a/>\n\n")
|
|
end
|
|
|
|
# Contributed (with patch to fix bug) by Kouhei
|
|
def test_ignore_whitespace
|
|
source = "<a> <b/> abc <![CDATA[def]]> </a>"
|
|
|
|
context_all = {:ignore_whitespace_nodes => :all}
|
|
context_a = {:ignore_whitespace_nodes => %(a)}
|
|
context_b = {:ignore_whitespace_nodes => %(b)}
|
|
|
|
tests = [[[" abc ", "def"], context_all],
|
|
[[" abc ", "def"], context_a],
|
|
[[" ", " abc ", "def", " "], context_b]]
|
|
|
|
tests.each do |test|
|
|
assert_equal(test[0], Document.new(source, test[1]).root.texts.collect{|x|
|
|
x.to_s})
|
|
end
|
|
end
|
|
|
|
def test_0xD_in_preface
|
|
doc = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\x0D<opml version=\"1.0\">\x0D</opml>"
|
|
doc = Document.new doc
|
|
end
|
|
|
|
def test_hyphens_in_doctype
|
|
doc = REXML::Document.new <<-EOQ
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE a-b-c>
|
|
<a-b-c>
|
|
<a/>
|
|
</a-b-c>
|
|
EOQ
|
|
|
|
assert_equal('a-b-c', doc.doctype.name)
|
|
end
|
|
|
|
def test_accents
|
|
docs = [
|
|
%Q{<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
<gnuPod>
|
|
<files>
|
|
<file id="57" artist="Coralie Cl\357\277\275ent" />
|
|
</files>
|
|
</gnuPod>},
|
|
'<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
<gnuPod>
|
|
<files>
|
|
<file id="71" album="Astrakan Caf" />
|
|
</files>
|
|
</gnuPod>',
|
|
%Q{<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
<gnuPod>
|
|
<files>
|
|
<file id="71" album="Astrakan Caf\357\277\275eria" />
|
|
</files>
|
|
</gnuPod>},
|
|
%Q{<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
<gnuPod>
|
|
<files>
|
|
<file id="71" album="Astrakan Caf\357\277\275" />
|
|
</files>
|
|
</gnuPod>} ]
|
|
docs.each_with_index { |d,i|
|
|
begin
|
|
REXML::Document.new(d)
|
|
rescue
|
|
puts "#{i} => #{docs[i]}"
|
|
raise
|
|
end
|
|
}
|
|
end
|
|
|
|
def test_replace_text
|
|
e = REXML::Element.new( "a" )
|
|
e.add_text( "foo" )
|
|
assert_equal( "<a>foo</a>", e.to_s )
|
|
e[0].value = "bar"
|
|
assert_equal( "<a>bar</a>", e.to_s )
|
|
e[0].value = "<"
|
|
assert_equal( "<a><</a>", e.to_s )
|
|
assert_equal( "<", e[0].value )
|
|
end
|
|
|
|
|
|
def test_write_doctype
|
|
## XML Document and Declaration
|
|
document = REXML::Document.new
|
|
xmldecl = REXML::XMLDecl.new("1.0", "UTF-8")
|
|
document.add(xmldecl)
|
|
s = ""
|
|
document.write(s)
|
|
|
|
## XML Doctype
|
|
str = '<!DOCTYPE foo "bar">'
|
|
source = REXML::Source.new(str)
|
|
doctype = REXML::DocType.new(source)
|
|
document.add(doctype)
|
|
document.write(s)
|
|
|
|
## Element
|
|
element = REXML::Element.new("hoge")
|
|
document.add(element)
|
|
|
|
document.write(s)
|
|
end
|
|
|
|
def test_write_cdata
|
|
src = "<a>A</a>"
|
|
doc = REXML::Document.new( src )
|
|
out = ""
|
|
doc.write( out )
|
|
assert_equal( src, out )
|
|
|
|
src = "<a><![CDATA[A]]></a>"
|
|
doc = REXML::Document.new( src )
|
|
out = ""
|
|
doc.write( out )
|
|
assert_equal( src, out )
|
|
end
|
|
|
|
def test_namespace_attributes
|
|
source = <<-EOL
|
|
<a xmlns:x="1">
|
|
<x:b x:n="foo"/>
|
|
</a>
|
|
EOL
|
|
d = Document.new( source )
|
|
assert_equal( 'foo', REXML::XPath.first(d.root, "//x:b/@x:n").value )
|
|
assert_equal( nil, REXML::XPath.first(d.root, "//x:b/@x:n", {}))
|
|
end
|
|
|
|
def test_null_element_name
|
|
a = REXML::Document.new
|
|
assert_raise( RuntimeError ) {
|
|
a.add_element( nil )
|
|
}
|
|
end
|
|
|
|
def test_text_raw
|
|
# From the REXML tutorial
|
|
# (http://www.germane-software.com/software/rexml/test/data/tutorial.html)
|
|
doc = Document.new <<-EOL
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE schema SYSTEM "XMLSchema.dtd" [
|
|
<!ENTITY % s 'Sean'>
|
|
]>
|
|
<a/>
|
|
EOL
|
|
a = doc.root
|
|
|
|
# This makes sure that RAW text nodes don't have their entity strings
|
|
# replaced
|
|
t = Text.new "Sean", false, nil, true
|
|
a.text = t
|
|
assert_equal( "Sean", t.to_s )
|
|
assert_equal( "Sean", t.value )
|
|
|
|
# This makes sure that they do
|
|
t = Text.new "Sean", false, nil, false
|
|
a.text = t
|
|
assert_equal( "&s;", t.to_s )
|
|
assert_equal( "Sean", t.value )
|
|
|
|
t = Text.new "&s;", false, nil, true
|
|
a.text = t
|
|
assert_equal( "&s;", t.to_s )
|
|
assert_equal( "Sean", t.value )
|
|
|
|
t = Text.new "&s;", false, nil, true
|
|
a.text = t
|
|
assert_equal( "&s;", t.to_s )
|
|
assert_equal( "Sean", t.value )
|
|
|
|
# Ticket #44
|
|
t = REXML::Text.new( "&", false, nil, true )
|
|
assert_equal( "&", t.to_s )
|
|
|
|
t = REXML::Text.new("&", false, false)
|
|
assert_equal( "&amp;", t.to_s )
|
|
end
|
|
|
|
def test_to_xpath
|
|
doc = REXML::Document.new( %q{<tag1>
|
|
<tag2 name="tag2"/>
|
|
<tag2 name="tag2"/>
|
|
</tag1>})
|
|
names = %w{ /tag1/tag2[1] /tag1/tag2[2] }
|
|
doc.root.elements.each_with_index {|el, i|
|
|
assert_equal( names[i], el.xpath )
|
|
}
|
|
end
|
|
|
|
def test_transitive
|
|
doc = REXML::Document.new( "<a/>")
|
|
s = ""
|
|
doc.write( s, 0, true )
|
|
end
|
|
|
|
# This is issue #40
|
|
def test_replace_with
|
|
old = '<doc>old<foo/>old</doc>'
|
|
d = REXML::Document.new(old).root
|
|
new = REXML::Text.new('new',true,nil,true)
|
|
child = d.children[2]
|
|
child.replace_with(new)
|
|
assert_equal( new, d.children[2] )
|
|
end
|
|
|
|
def test_repeated_writes
|
|
a = IO.read(fixture_path("iso8859-1.xml"))
|
|
f = REXML::Formatters::Pretty.new
|
|
|
|
xmldoc = REXML::Document.new( a )
|
|
a_andre = xmldoc.elements['//image'].attributes['caption']
|
|
|
|
f.write(xmldoc,b="")
|
|
|
|
xmldoc = REXML::Document.new(b)
|
|
b_andre = xmldoc.elements['//image'].attributes['caption']
|
|
assert_equal( a_andre, b_andre )
|
|
|
|
f.write(xmldoc,c="")
|
|
|
|
xmldoc = REXML::Document.new(c)
|
|
c_andre = xmldoc.elements['//image'].attributes['caption']
|
|
assert_equal( b_andre, c_andre )
|
|
|
|
o = Output.new(d="","UTF-8")
|
|
f.write(xmldoc,o)
|
|
assert_not_equal( c, d )
|
|
end
|
|
|
|
def test_pretty_format_long_text_finite
|
|
n = 1_000_000
|
|
long_text = 'aaaa ' * n
|
|
xml = "<doc>#{long_text}</doc>"
|
|
formatter = REXML::Formatters::Pretty.new
|
|
document = nil
|
|
begin
|
|
document = REXML::Document.new(xml)
|
|
rescue REXML::ParseException
|
|
skip_message = "skip this test because we can't check Pretty#wrap " +
|
|
"works without #<SystemStackError: stack level too deep> on " +
|
|
"small memory system. #<RegexpError: failed to allocate memory> " +
|
|
"will be raised on the system. See also [ruby-dev:42599]."
|
|
return skip_message
|
|
end
|
|
output = ""
|
|
formatter.write(document, output)
|
|
assert_equal("<doc>\n" +
|
|
((" " + (" aaaa" * 15) + "\n") * (n / 15)) +
|
|
" " + ("aaaa " * (n % 15)) + "\n" +
|
|
"</doc>",
|
|
output)
|
|
end
|
|
|
|
def test_pretty_format_deep_indent
|
|
n = 6
|
|
elements = ""
|
|
n.times do |i|
|
|
elements << "<element#{i}>"
|
|
elements << "element#{i} " * 5
|
|
end
|
|
(n - 1).downto(0) do |i|
|
|
elements << "</element#{i}>"
|
|
end
|
|
xml = "<doc>#{elements}</doc>"
|
|
document = REXML::Document.new(xml)
|
|
formatter = REXML::Formatters::Pretty.new
|
|
formatter.width = 20
|
|
output = ""
|
|
formatter.write(document, output)
|
|
assert_equal(<<-XML.strip, output)
|
|
<doc>
|
|
<element0>
|
|
element0
|
|
element0
|
|
element0
|
|
element0
|
|
element0\s
|
|
<element1>
|
|
element1
|
|
element1
|
|
element1
|
|
element1
|
|
element1\s
|
|
<element2>
|
|
element2
|
|
element2
|
|
element2
|
|
element2
|
|
element2\s
|
|
<element3>
|
|
element3
|
|
element3
|
|
element3
|
|
element3
|
|
element3\s
|
|
<element4>
|
|
element4
|
|
element4
|
|
element4
|
|
element4
|
|
element4
|
|
\s
|
|
<element5>
|
|
element5 element5 element5 element5 element5\s
|
|
</element5>
|
|
</element4>
|
|
</element3>
|
|
</element2>
|
|
</element1>
|
|
</element0>
|
|
</doc>
|
|
XML
|
|
end
|
|
|
|
def test_ticket_58
|
|
doc = REXML::Document.new
|
|
doc << REXML::XMLDecl.default
|
|
doc << REXML::Element.new("a")
|
|
|
|
str = ""
|
|
doc.write(str)
|
|
|
|
assert_equal("<a/>", str)
|
|
|
|
doc = REXML::Document.new
|
|
doc << REXML::XMLDecl.new("1.0", "UTF-8")
|
|
doc << REXML::Element.new("a")
|
|
|
|
str = ""
|
|
doc.write(str)
|
|
|
|
assert_equal("<?xml version='1.0' encoding='UTF-8'?><a/>", str)
|
|
end
|
|
|
|
# Incomplete tags should generate an error
|
|
def test_ticket_53
|
|
assert_raise( REXML::ParseException ) {
|
|
REXML::Document.new( "<a><b></a>" )
|
|
}
|
|
assert_raise( REXML::ParseException ) {
|
|
REXML::Document.new( "<a><b>" )
|
|
}
|
|
assert_raise( REXML::ParseException ) {
|
|
REXML::Document.new( "<a><b/>" )
|
|
}
|
|
end
|
|
|
|
def test_ticket_52
|
|
source = "<!-- this is a single line comment -->"
|
|
d = REXML::Document.new(source)
|
|
d.write(k="")
|
|
assert_equal( source, k )
|
|
|
|
source = "<a><!-- Comment --></a>"
|
|
target = "<a>\n <!-- Comment -->\n</a>"
|
|
d = REXML::Document.new(source)
|
|
REXML::Formatters::Pretty.new(4).write(d,k="")
|
|
assert_equal( target, k )
|
|
end
|
|
|
|
def test_ticket_76
|
|
src = "<div>at&t"
|
|
assert_raise( ParseException, %Q{"#{src}" is invalid XML} ) {
|
|
REXML::Document.new(src)
|
|
}
|
|
end
|
|
|
|
def test_ticket_21
|
|
src = "<foo bar=value/>"
|
|
exception = assert_raise(ParseException) do
|
|
Document.new(src)
|
|
end
|
|
assert_equal(<<-DETAIL, exception.to_s)
|
|
Missing attribute value start quote: <bar>
|
|
Line: 1
|
|
Position: 16
|
|
Last 80 unconsumed characters:
|
|
DETAIL
|
|
end
|
|
|
|
def test_ticket_63
|
|
File.open(fixture_path("t63-1.xml")) {|f| Document.new(f) }
|
|
end
|
|
|
|
def test_ticket_75
|
|
d = File.open(fixture_path("t75.xml")) {|f| REXML::Document.new(f) }
|
|
assert_equal("tree", d.root.name)
|
|
end
|
|
|
|
def test_ticket_48_part_II
|
|
f = REXML::Formatters::Pretty.new
|
|
#- rexml sanity check (bugs in ruby 1.8.4, ruby 1.8.6)
|
|
xmldoc = Document.new("<test/>")
|
|
xmldoc << XMLDecl.new(XMLDecl::DEFAULT_VERSION, "UTF-8")
|
|
content = ['61c3a927223c3e26'].pack("H*")
|
|
content.force_encoding('UTF-8') if content.respond_to?(:force_encoding)
|
|
#- is some UTF-8 text but just to make sure my editor won't magically convert..
|
|
xmldoc.root.add_attribute('attr', content)
|
|
f.write(xmldoc,out=[])
|
|
|
|
xmldoc = REXML::Document.new(out.join)
|
|
sanity1 = xmldoc.root.attributes['attr']
|
|
f.write(xmldoc,out=[])
|
|
|
|
xmldoc = REXML::Document.new(out.join)
|
|
sanity2 = xmldoc.root.attributes['attr']
|
|
f.write(xmldoc,out=[])
|
|
|
|
assert_equal( sanity1, sanity2 )
|
|
end
|
|
|
|
def test_ticket_88
|
|
doc = REXML::Document.new("<?xml version=\"1.0\" encoding=\"shift_jis\"?>")
|
|
assert_equal("<?xml version='1.0' encoding='SHIFT_JIS'?>", doc.to_s)
|
|
doc = REXML::Document.new("<?xml version = \"1.0\" encoding = \"shift_jis\"?>")
|
|
assert_equal("<?xml version='1.0' encoding='SHIFT_JIS'?>", doc.to_s)
|
|
end
|
|
|
|
def test_ticket_85
|
|
xml = <<ENDXML
|
|
<foo>
|
|
<bar>
|
|
<bob name='jimmy'/>
|
|
</bar>
|
|
</foo>
|
|
ENDXML
|
|
|
|
yml = "<foo>
|
|
<bar>
|
|
<bob name='jimmy'/>
|
|
</bar>
|
|
</foo>"
|
|
|
|
# The pretty printer ignores all whitespace, anyway so output1 == output2
|
|
f = REXML::Formatters::Pretty.new( 2 )
|
|
d = Document.new( xml, :ignore_whitespace_nodes=>:all )
|
|
f.write( d, output1="" )
|
|
|
|
d = Document.new( xml )
|
|
f.write( d, output2="" )
|
|
|
|
# Output directives should override whitespace directives.
|
|
assert_equal( output1, output2 )
|
|
|
|
# The base case.
|
|
d = Document.new(yml)
|
|
f.write( d, output3="" )
|
|
|
|
assert_equal( output3.strip, output2.strip )
|
|
|
|
d = Document.new(yml)
|
|
f.write( d, output4="" )
|
|
|
|
assert_equal( output3.strip, output4.strip )
|
|
end
|
|
|
|
def test_ticket_91
|
|
source="<root>
|
|
<bah something='1' somethingelse='bah'>
|
|
<something>great</something>
|
|
</bah>
|
|
</root>"
|
|
expected="<root>
|
|
<bah something='1' somethingelse='bah'>
|
|
<something>great</something>
|
|
</bah>
|
|
<bah/>
|
|
</root>"
|
|
d = Document.new( source )
|
|
d.root.add_element( "bah" )
|
|
p=REXML::Formatters::Pretty.new(2)
|
|
p.compact = true # Don't add whitespace to text nodes unless necessary
|
|
p.write(d,out="")
|
|
assert_equal( expected, out )
|
|
end
|
|
|
|
def test_ticket_95
|
|
testd = REXML::Document.new "<a><b><c/><c/><c/></b></a>"
|
|
testd.write(out1="")
|
|
testd.elements["//c[2]"].xpath
|
|
testd.write(out2="")
|
|
assert_equal(out1,out2)
|
|
end
|
|
|
|
def test_ticket_102
|
|
doc = REXML::Document.new '<doc xmlns="ns"><item name="foo"/></doc>'
|
|
assert_equal( "foo", doc.root.elements["*:item"].attribute("name","ns").to_s )
|
|
assert_equal( "item", doc.root.elements["*:item[@name='foo']"].name )
|
|
end
|
|
|
|
def test_ticket_14
|
|
# Per .2.5 Node Tests of XPath spec
|
|
assert_raise( REXML::UndefinedNamespaceException,
|
|
%Q{Should have gotten an Undefined Namespace error} ) {
|
|
Document.new("<a><n:b/></a>")
|
|
}
|
|
end
|
|
|
|
# 5.7 Text Nodes
|
|
# Character data is grouped into text nodes. As much character data as
|
|
# possible is grouped into each text node: a text node never has an
|
|
# immediately following or preceding sibling that is a text node. The
|
|
# string-value of a text node is the character data. A text node always has
|
|
# at least one character of data.
|
|
def test_ticket_105
|
|
d = Document.new("<a/>")
|
|
d.root.add_text( "a" )
|
|
d.root.add_text( "b" )
|
|
assert_equal( 1, d.root.children.size )
|
|
end
|
|
|
|
# phantom namespace same as default namespace
|
|
def test_ticket_121
|
|
doc = REXML::Document.new(
|
|
'<doc xmlns="ns" xmlns:phantom="ns"><item name="foo">text</item></doc>'
|
|
)
|
|
assert_equal 'text', doc.text( "/*:doc/*:item[@name='foo']" )
|
|
assert_equal "name='foo'",
|
|
doc.root.elements["*:item"].attribute("name", "ns").inspect
|
|
assert_equal "<item name='foo'>text</item>",
|
|
doc.root.elements["*:item[@name='foo']"].to_s
|
|
end
|
|
|
|
def test_ticket_135
|
|
bean_element = REXML::Element.new("bean")
|
|
textToAdd = "(&(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))"
|
|
bean_element.add_element("prop", {"key"=> "filter"}).add_text(textToAdd)
|
|
doc = REXML::Document.new
|
|
doc.add_element(bean_element)
|
|
|
|
REXML::Formatters::Pretty.new(3).write( doc, out = "" )
|
|
|
|
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
|
|
end
|
|
|
|
def test_ticket_138
|
|
doc = REXML::Document.new(
|
|
'<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" ' +
|
|
'inkscape:version="0.44" version="1.0"/>'
|
|
)
|
|
expected = {
|
|
"inkscape" => attribute("xmlns:inkscape",
|
|
"http://www.inkscape.org/namespaces/inkscape"),
|
|
"version" => {
|
|
"inkscape" => attribute("inkscape:version", "0.44"),
|
|
"" => attribute("version", "1.0"),
|
|
},
|
|
}
|
|
assert_equal(expected, doc.root.attributes)
|
|
assert_equal(expected, REXML::Document.new(doc.root.to_s).root.attributes)
|
|
end
|
|
|
|
def test_empty_doc
|
|
assert(REXML::Document.new('').children.empty?)
|
|
end
|
|
|
|
private
|
|
def attribute(name, value)
|
|
REXML::Attribute.new(name, value)
|
|
end
|
|
end
|
|
end
|