From 9a695f113abf98038a53878a8bb6ee054f893497 Mon Sep 17 00:00:00 2001 From: kou Date: Sat, 22 Feb 2014 11:25:47 +0000 Subject: * test/rexml/test_xpath*.rb: Move to ... * test/rexml/xpath/*.rb: ... here. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45133 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/rexml/test_xpath.rb | 1079 ----------------------- test/rexml/test_xpath_attribute_query.rb | 89 -- test/rexml/test_xpath_msw.rb | 38 - test/rexml/test_xpath_pred.rb | 80 -- test/rexml/test_xpathtext.rb | 72 -- test/rexml/xpath/test_attribute.rb | 85 ++ test/rexml/xpath/test_axis_preceding_sibling.rb | 38 + test/rexml/xpath/test_base.rb | 1079 +++++++++++++++++++++++ test/rexml/xpath/test_predicate.rb | 80 ++ test/rexml/xpath/test_text.rb | 72 ++ 10 files changed, 1354 insertions(+), 1358 deletions(-) delete mode 100644 test/rexml/test_xpath.rb delete mode 100644 test/rexml/test_xpath_attribute_query.rb delete mode 100644 test/rexml/test_xpath_msw.rb delete mode 100644 test/rexml/test_xpath_pred.rb delete mode 100644 test/rexml/test_xpathtext.rb create mode 100644 test/rexml/xpath/test_attribute.rb create mode 100644 test/rexml/xpath/test_axis_preceding_sibling.rb create mode 100644 test/rexml/xpath/test_base.rb create mode 100644 test/rexml/xpath/test_predicate.rb create mode 100644 test/rexml/xpath/test_text.rb (limited to 'test/rexml') diff --git a/test/rexml/test_xpath.rb b/test/rexml/test_xpath.rb deleted file mode 100644 index 927909a5f2..0000000000 --- a/test/rexml/test_xpath.rb +++ /dev/null @@ -1,1079 +0,0 @@ -require_relative "rexml_test_utils" - -require "rexml/document" - -class XPathTester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - SOURCE = <<-EOF - - - - - - - - - - - - - - - - - - - - - - -

- - - - - EOF - JENI_TENNISON = <<-EOJT - - - - - - - - - - - - - - - - - - - - - - - - EOJT - - def setup - @@doc = Document.new(SOURCE) unless defined? @@doc - @@jeni = Document.new( JENI_TENNISON ) unless defined? @@jeni - end - - def each_test( element, xpath ) - count = 0 - XPath::each( element, xpath ) { |child| - count += 1 - yield child if block_given? - } - count - end - - def test_descendant - doc = Document.new("") - p = XPath.match( doc, "//c" ) - assert_equal( 2, p.size ) - p = XPath.first( @@doc, "//p" ) - assert_equal "p", p.name - c = each_test( @@doc, "//c" ) { |child| assert_equal "c", child.name } - assert_equal 5, c - c = each_test( @@doc.root, "b//c" ) { |child| - assert_equal "c", child.name - } - assert_equal 2, c - - doc = Document.new( "" ) - # //para[1] : all descendants which are the first para child of their parent - assert_equal( 4, XPath.match( doc, "//z[1]" ).size ) - # /descendant::para[1] : the first descendant para element - assert_equal( 1, XPath.match( doc, "/descendant::z[1]" ).size ) - end - - def test_root - source = "" - doc = Document.new( source ) - assert_equal doc, doc.root_node - assert_equal "a", XPath::first( doc, "/" ).elements[1].name - end - - def test_abbreviated_simple_child - assert_equal "a", XPath::first(@@doc, "a").name - end - - def test_child - c = XPath::first( @@doc, "a/b/c" ) - assert_equal "c", c.name - assert_equal "3", XPath::first(@@doc, "a/b/c").attributes["id"] - end - - def test_root_child - assert_equal "a", XPath::first(@@doc, "/a").name - c = XPath::first( @@doc, "a/b/c" ) - assert_equal "a", XPath::first(c, "/a").name - end - - def test_root_children - c = XPath::first( @@doc, "a/b/c" ) - assert_equal "2", XPath::first(c, "/a/b").attributes["id"] - end - - def test_abbreviated_step - c = XPath::first( @@doc, "a/b/c" ) - assert_equal("c", c.name) - assert_equal("a", XPath::first(@@doc.root, ".").name) - assert_equal("b", XPath::first(c, "..").name) - assert_equal("a", XPath::first(@@doc, "a/b/..").name) - - doc = REXML::Document.new(File.new(fixture_path("project.xml"))) - c = each_test(doc.root, "./Description" ) { |child| - assert_equal("Description",child.name) - } - assert_equal 1, c - end - - # Things that aren't tested elsewhere - def test_predicates - assert_equal "12", XPath::first(@@doc, "a/e/f[3]").attributes["id"] - assert_equal "13", XPath::first(@@doc, "a/e/f[3]/g").attributes["id"] - assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][2]").attributes["id"] - assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][@id='14']").attributes["id"] - assert_equal "a", XPath::first( @@doc, "*[name()='a' and @id='1']" ).name - c=each_test( @@doc, "//*[name()='f' and @a='d']") { |i| - assert_equal "f", i.name - } - assert_equal 2, c - c=each_test( @@doc, "//*[name()='m' or @a='d']") { |i| - assert ["m","f"].include?(i.name) - } - assert_equal 3, c - - assert_equal "b", XPath::first( @@doc, "//b[@x]" ).name - end - - def test_node_type - doc = Document.new "text" - #res = XPath::first(doc.root, "text()") - #assert_equal "text", res.to_s - - #res = XPath::first(doc, "*") - #assert_equal "a", res.name - - assert_equal( :processing_instruction, - XPath::first(doc.root, "processing-instruction()").node_type) - assert_equal( :comment, XPath::first(doc.root, "comment()").node_type) - end - - def test_functions - # trivial text() test - # confuse-a-function - source = "more dumb text" - doc = Document.new source - res = "" - #XPath::each(doc.root, "text()") {|val| res << val.to_s} - #assert_equal "more text", res - - #res = XPath::first(doc.root, "b[last()]") - #assert_equal '3', res.attributes['id'] - res = XPath::first(doc.root, "b[position()=2]") - assert_equal '2', res.attributes['id'] - res = XPath::first(doc.root, "*[name()='c']") - assert_equal "c", res.name - end - - def no_test_ancestor - doc = REXML::Document.new(File.new(fixture_path("testsrc.xml"))) - doc.elements.each("//item") { |el| print el.name - if el.attributes['x'] - puts " -- "+el.attributes['x'] - else - puts - end - } - doc.elements.each("//item/ancestor::") { |el| print el.name - if el.attributes['x'] - puts " -- "+el.attributes['x'] - else - puts - end - } - end - - # Here are some XPath tests that were originally submitted by ... - # The code has changed some, but the logic and the source documents are the - # same. - # This method reads a document from a file, and then a series of xpaths, - # also from a file. It then checks each xpath against the source file. - def test_more - xmlsource = fixture_path("testsrc.xml") - xpathtests = fixture_path("xp.tst") - - doc = REXML::Document.new(File.new(xmlsource)) - #results = "" - results = REXML::Document.new - results.add_element "test-results" - for line in File.new(xpathtests) - line.strip! - begin - doc.root - #puts "#"*80 - #print "\nDoing #{line} " ; $stdout.flush - doc.elements.each(line) do |el| - #print "." ; $stdout.flush - results.root << el.clone - #results << el.to_s - end - #ObjectSpace.garbage_collect - GC::start - rescue Exception => z - #puts "\n'#{line}' failed" - fail("Error on line #{line}:\n#{z.message}\n"+z.backtrace[0,10].join("\n")) - #results.root.add_element( "error", {"path"=>line}).text = z.message+"\n"+z.backtrace[0,10].join("\n") - #results << ""+z.message+"" - end - end - end - - def test_axe_descendant - assert_equal "f", XPath::first( @@doc, "descendant::f").name - end - - def test_axe_parent - q = XPath.first( @@doc, "a/d/c/parent::*/q" ) - assert_equal 19, q.attributes["id"].to_i - end - - def test_abbreviated_attribute - assert_equal 'a', XPath::first( @@doc, "a[@id='1']" ).name - c = XPath::first( @@doc, "a/b/c[@id='4']" ) - assert_equal 'c', c.name - assert_equal '4', c.attributes['id'] - - result = XPath::first( @@doc, "descendant::f[@a='c']") - assert_equal "11", result.attributes['id'] - - assert_equal "11", XPath::first(@@doc, "a/e/f[@a='c']").attributes["id"] - assert_equal "11", XPath::first(@@doc, "a/e/*[@a='c']").attributes["id"] - end - - def test_axe_self - c = XPath::first( @@doc, "a/b/c" ) - assert c - assert_equal "c", c.name - assert_equal "c", XPath::first( c, "self::node()" ).name - end - - def test_axe_ancestor - doc = REXML::Document.new " - - - - - - - - - " - - d = XPath.first( doc, "//d" ) - assert_equal "d", d.name - b = each_test( d, "ancestor::b" ) { |el| - assert((1..2) === el.attributes['id'].to_i, - "Expected #{el.attributes['id']} to be either 1 or 2" - ) - } - assert_equal 2, b - end - - def test_axe_child - m = XPath.first( @@doc, "a/child::m" ) - assert_equal 15, m.attributes['id'].to_i - end - - def test_axe_attribute - a = XPath.first( @@doc, "a/attribute::id" ) - assert_equal "1", a.value - a = XPath.first( @@doc, "a/e/f[@id='14']/attribute::a" ) - assert_equal "d", a.value - end - - def test_axe_sibling - doc = Document.new "" - first_f = XPath.first( doc, "a/e/f" ) - assert first_f - assert_equal '10', first_f.attributes['id'] - next_f = XPath.first( doc, "a/e/f/following-sibling::node()" ) - assert_equal '11', next_f.attributes['id'] - - b = XPath.first( doc, "a/e/preceding-sibling::node()" ) - assert_equal 'b', b.name - end - - def test_lang - doc = Document.new(File.new(fixture_path("lang0.xml"))) - #puts IO.read( "test/lang.xml" ) - - #puts XPath.match( doc, "//language/*" ).size - c = each_test( doc, "//language/*" ) { |element| - #puts "#{element.name}: #{element.text}" - } - assert_equal 4, c - end - - def test_namespaces_1 - source = <<-EOF - - this bar - that bar - - EOF - doc = Document.new source - XPath.each( doc, "//bar" ) { - fail "'bar' should match nothing in this case" - } - - namespace = {"t"=>"this"} - results = XPath.first( doc, "//t:bar", namespace ) - assert_equal "this bar", results.text - end - - def test_namespaces_2 - source = <<-EOF - - this bar - that bar - - EOF - doc = Document.new source - res = XPath::first(doc, "//*[local_name()='bar']") - assert res, "looking for //*[name()='bar']" - assert_equal 'this', res.namespace - res = XPath::first(doc.root, "*[namespace_uri()='that']") - assert_equal 'that bar', res.text - end - - def test_complex - next_f = XPath.first( @@doc, "a/e/f[@id='11']/following-sibling::*" ) - assert_equal 12, next_f.attributes['id'].to_i - prev_f = XPath.first( @@doc, "a/e/f[@id='11']/preceding-sibling::*" ) - assert_equal 10, prev_f.attributes['id'].to_i - c = each_test( @@doc, "descendant-or-self::*[@x='y']" ) - assert_equal 2, c - end - - def test_grouping - t = XPath.first( @@doc, "a/d/*[name()='d' and (name()='f' or name()='q')]" ) - assert_nil t - t = XPath.first( @@doc, "a/d/*[(name()='d' and name()='f') or name()='q']" ) - assert_equal 'q', t.name - end - - def test_preceding - d = Document.new "" - start = XPath.first( d, "/a/b[@id='1']" ) - assert_equal 'b', start.name - c = XPath.first( start, "preceding::c" ) - assert_equal '2', c.attributes['id'] - - c1, c0 = XPath.match( d, "/a/b/c[@id='2']/preceding::node()" ) - assert_equal '1', c1.attributes['id'] - assert_equal '0', c0.attributes['id'] - - c2, c1, c0, b, b2, b0 = XPath.match( start, "preceding::node()" ) - - assert_equal 'c', c2.name - assert_equal 'c', c1.name - assert_equal 'c', c0.name - assert_equal 'b', b.name - assert_equal 'b', b2.name - assert_equal 'b', b0.name - - assert_equal '2', c2.attributes['id'] - assert_equal '1', c1.attributes['id'] - assert_equal '0', c0.attributes['id'] - assert b.attributes.empty? - assert_equal '2', b2.attributes['id'] - assert_equal '0', b0.attributes['id'] - - d = REXML::Document.new("") - matches = REXML::XPath.match(d, "/a/d/preceding::node()") - assert_equal("c", matches[0].name) - assert_equal("b", matches[1].name) - - s = "" - d = REXML::Document.new(s) - c = REXML::XPath.match( d, "//c[@id = '5']") - cs = REXML::XPath.match( c, "preceding::c" ) - assert_equal( 4, cs.length ) - end - - def test_following - d = Document.new "" - start = XPath.first( d, "/a/b[@id='0']" ) - assert_equal 'b', start.name - c = XPath.first( start, "following::c" ) - assert_equal '1', c.attributes['id'] - - s = "" - d = Document.new(s) - c = XPath.first(d, '/a/b/c') - assert_equal 'c', c.name - res = XPath.match( c, 'following::*' ) - assert_equal 6, res.size - res = XPath.match( c, 'following::i' ) - assert_equal 2, res.size - end - - # The following three paths were provided by - # Jeni Tennison - # a consultant who is also an XSL and XPath expert - #def test_child_cubed - # els = @@jeni.elements.to_a("*****") - # assert_equal 3, els.size - #end - - #def test_div_2 - # results = doc.elements.to_a("/ div 2") - #end - - #def test_nested_predicates - # puts @@jeni.root.elements[1].elements[1].name - # results = @@jeni.root.elements[1].elements[1].elements.to_a("../following-sibling::*[*[name() = name(current())]]") - # puts results - #end - - # Contributed by Mike Stok - def test_starts_with - source = <<-EOF - - a@b.c - http://www.foo.com - - EOF - doc = Document.new source - mailtos = doc.elements.to_a("//a[starts-with(@href, 'mailto:')]") - assert_equal 1, mailtos.size - assert_equal "mailto:a@b.c", mailtos[0].attributes['href'] - - ailtos = doc.elements.to_a("//a[starts-with(@href, 'ailto:')]") - assert_equal 0, ailtos.size - end - - def test_toms_text_node - file = "ABCDEF" - doc = Document.new(file) - assert_equal 'A', XPath.first(doc[0], 'text()').to_s - assert_equal 'AF', XPath.match(doc[0], 'text()').collect { |n| - n.to_s - }.join('') - assert_equal 'B', XPath.first(doc[0], 'b/text()').to_s - assert_equal 'D', XPath.first(doc[0], '//d/text()').to_s - assert_equal 'ABCDEF', XPath.match(doc[0], '//text()').collect {|n| - n.to_s - }.join('') - end - - def test_string_length - doc = Document.new <<-EOF - - - - - - - - - EOF - assert doc, "create doc" - - set = doc.elements.to_a("//*[string-length(name()) = 3]") - assert_equal 2, set.size, "nodes with names length = 3" - - set = doc.elements.to_a("//*[string-length(name()) < 3]") - assert_equal 2, set.size, "nodes with names length < 3" - - set = doc.elements.to_a("//*[string-length(name()) > 3]") - assert_equal 3, set.size, "nodes with names length > 3" - end - - # Test provided by Mike Stok - def test_contains - source = <<-EOF - - a@b.c - http://www.foo.com - - EOF - doc = Document.new source - - [ - #['o', 2], - ['foo', 1], ['bar', 0]].each { |search, expected| - set = doc.elements.to_a("//a[contains(@href, '#{search}')]") - assert_equal expected, set.size - } - end - - # Mike Stok and Sean Russell - def test_substring - # examples from http://www.w3.org/TR/xpath#function-substring - doc = Document.new('') - - Document.new("") - #puts XPath.first(d, 'node()[0 + 1]') - #d = Document.new("") - #puts XPath.first(d, 'a[0 mod 0]') - [ [1.5, 2.6, '234'], - [0, 3, '12'], - [0, '0 div 0', ''], - [1, '0 div 0', ''], - ['-42', '1 div 0', '12345'], - ['-1 div 0', '1 div 0', ''] - ].each { |start, length, expected| - set = doc.elements.to_a("//test[substring(@string, #{start}, #{length}) = '#{expected}']") - assert_equal 1, set.size, "#{start}, #{length}, '#{expected}'" - } - end - - def test_translate - source = <<-EOF - - - - - - - - EOF - - doc = Document.new(source) - - [ ['bar', 'abc', 'ABC', 'w3c one'], - ['--aaa--','abc-','ABC', 'w3c two'], - ['lead', 'dear language', 'doll groover', 'alchemy'], - ['A Space Odissei', 'i', 'y', 'vbxml one'], - ['abcdefg', 'aceg', 'ACE', 'vbxml two'], - ].each { |arg1, arg2, arg3, name| - translate = "translate('#{arg1}', '#{arg2}', '#{arg3}')" - set = doc.elements.to_a("//case[@result = #{translate}]") - assert_equal 1, set.size, translate - assert_equal name, set[0].attributes['name'] - } - end - - def test_math - d = Document.new( '' ) - assert XPath.first( d.root, 'node()[1]' ) - assert_equal 'b', XPath.first( d.root, 'node()[1]' ).name - assert XPath.first( d.root, 'node()[0 + 1]' ) - assert_equal 'b', XPath.first( d.root, './node()[0 + 1]' ).name - assert XPath.first( d.root, 'node()[1 + 1]' ) - assert_equal 'c', XPath.first( d.root, './node()[1 + 1]' ).name - assert XPath.first( d.root, 'node()[4 div 2]' ) - assert_equal 'c', XPath.first( d.root, './node()[4 div 2]' ).name - assert XPath.first( d.root, 'node()[2 - 1]' ) - assert_equal 'b', XPath.first( d.root, './node()[2 - 1]' ).name - assert XPath.first( d.root, 'node()[5 mod 2]' ) - assert_equal 'b', XPath.first( d.root, './node()[5 mod 2]' ).name - assert XPath.first( d.root, 'node()[8 mod 3]' ) - assert_equal 'c', XPath.first( d.root, './node()[8 mod 3]' ).name - assert XPath.first( d.root, 'node()[1 * 2]' ) - assert_equal 'c', XPath.first( d.root, './node()[1 * 2]' ).name - assert XPath.first( d.root, 'node()[2 + -1]' ) - assert_equal 'b', XPath.first( d.root, './node()[2 + -1]' ).name - end - - def test_name - assert_raise( UndefinedNamespaceException, "x should be undefined" ) { - REXML::Document.new("") - } - d = REXML::Document.new("") - assert_equal 1, d.root.elements.to_a('*[name() = "b"]').size - assert_equal 1, d.elements.to_a('//*[name() = "x:b"]').size - end - - def test_local_name - d = REXML::Document.new("") - assert_equal 2, d.root.elements.to_a('*[local_name() = "b"]').size - assert_equal 2, d.elements.to_a('//*[local_name() = "b"]').size - end - - def test_comparisons - source = "" - doc = REXML::Document.new(source) - - # NOTE TO SER: check that number() is required - assert_equal 2, REXML::XPath.match(doc, "//b[number(@id) > 1]").size - assert_equal 3, REXML::XPath.match(doc, "//b[number(@id) >= 1]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) <= 1]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 * 1)]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 mod 2)]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (4 div 2)]").size - end - - # Contributed by Kouhei - def test_substring_before - doc = Document.new("") - assert_equal("a", doc.root.elements.to_a("*[name()=substring-before('abc', 'b')]")[0].name) - assert_equal("c", doc.root.elements.to_a("*[name()=substring-after('abc', 'b')]")[0].name) - end - - def test_spaces - doc = Document.new(" - - - - - ") - assert_equal( 1, REXML::XPath.match(doc, - "//*[local-name()='c' and @id='b']").size ) - assert_equal( 1, REXML::XPath.match(doc, - "//*[ local-name()='c' and @id='b' ]").size ) - assert_equal( 1, REXML::XPath.match(doc, - "//*[ local-name() = 'c' and @id = 'b' ]").size ) - assert_equal( 1, - REXML::XPath.match(doc, '/a/c[@id]').size ) - assert_equal( 1, - REXML::XPath.match(doc, '/a/c[(@id)]').size ) - assert_equal( 1, - REXML::XPath.match(doc, '/a/c[ @id ]').size ) - assert_equal( 1, - REXML::XPath.match(doc, '/a/c[ (@id) ]').size ) - assert_equal( 1, - REXML::XPath.match(doc, '/a/c[( @id )]').size ) - assert_equal( 1, REXML::XPath.match(doc.root, - '/a/c[ ( @id ) ]').size ) - assert_equal( 1, REXML::XPath.match(doc, - '/a/c [ ( @id ) ] ').size ) - assert_equal( 1, REXML::XPath.match(doc, - ' / a / c [ ( @id ) ] ').size ) - end - - def test_text_nodes - # source = " - # - #test - #" - source = "test" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/root/child[text()="test"]} ) - assert_equal( 1, r.size ) - assert_equal( "child", r[0].name ) - assert_equal( "test", r[0].text ) - end - - def test_auto_string_value - source = "Introduction" - d = REXML::Document.new( source ) - #r = REXML::XPath.match( d, %q{/root[title="Introduction"]} ) - #assert_equal( 1, r.size ) - source = "test" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/a[c='test']} ) - assert_equal( 1, r.size ) - r = REXML::XPath.match( d, %q{a[c='test']} ) - assert_equal( 1, r.size ) - r = d.elements["/a[c='test']"] - assert_not_nil( r ) - r = d.elements["a[c='test']"] - assert_not_nil( r ) - r = d.elements["a[c='xtest']"] - assert_nil( r ) - r = REXML::XPath.match( d, %q{a[c='xtest']} ) - assert_equal( 0, r.size ) - end - - def test_ordering - source = "" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/a/*/*[1]} ) - assert_equal( 1, r.size ) - r.each { |el| assert_equal( '1', el.attribute('id').value ) } - end - - def test_descendant_or_self_ordering - source = " - - - - - - - - - - - - - - - " - d = REXML::Document.new( source ) - cs = XPath.match( d, "/descendant-or-self::c" ) - assert_equal( 4, cs.length ) - 1.upto(4) {|x| assert_equal( x.to_s, cs[x-1].attributes['id'] ) } - end - - def test_and - d = Document.new %q{} - assert_equal( nil, d.root.elements["route[@run='0']"] ) - assert_equal( nil, d.root.elements["route[@run='0' and @title='HNO']"] ) - end - - - def test_numbers - d = Document.new %q{} - - xp1 = "/a[ @x = 0 ]" - xp2 = "/a[ @x = '0' ]" - xp3 = "/a[ (@x + 1) = 1 ]" - xp4 = "/a[ @y = 0 ]" - xp5 = "/a[ (@z + 1) = 5 ]" - xp6 = "/a[ (@w + 1) = 5 ]" - xp7 = "/a[ (@v + 1) = 1 ]" - xp8 = "/a[ @n = 0 ]" - - assert_equal( 1, XPath.match( d, xp1 ).length ) - assert_equal( 1, XPath.match( d, xp2 ).length ) - assert_equal( 1, XPath.match( d, xp3 ).length ) - assert_equal( 0, XPath.match( d, xp4 ).length ) - assert_equal( 0, XPath.match( d, xp5 ).length ) - assert_equal( 0, XPath.match( d, xp6 ).length ) - assert_equal( 0, XPath.match( d, xp7 ).length ) - assert_equal( 0, XPath.match( d, xp8 ).length ) - end - - def test_tobis_preceding - doc_string = ' - - - - - -' - - doc = Document.new(doc_string) - - # e = REXML::XPath.first(doc,'/a/c/e') - e = doc.root.get_elements('/a/c/e')[0] - assert_equal( 1, e.get_elements('preceding-sibling::*').length ) - assert_equal( 2, XPath.match(e, 'preceding::*').length ) - end - - - def test_filtering - #doc=Document.new("") - #assert_equal( 3, XPath.match( doc, '/a/b/*[1]' ).length ) - #assert_equal( 2, XPath.match( doc, '/a/b/following-sibling::*[1]' ).length ) - end - - # Submitted by Alex - def test_union - data = %Q{

- - a - - b -
} - rd = REXML::Document.new( data ) - #union = rd.get_elements("/div/span | /div/em") - #assert_equal(2, union.length, "/div/span | /div/em" ) - union = rd.get_elements('//*[name()="em" or name()="strong"]') - assert_equal(2, union.length, 'name() and "or" failed') - union = rd.get_elements('//em|//strong') - assert_equal(2, union.length, - 'Both tag types are returned by XPath union operator') - end - - - def test_union2 - src = <<-EOL -
- -a - -b -
- EOL - rd = REXML::Document.new( src ) - union = rd.get_elements('//em|//strong') - assert_equal(2, union.length, - 'Both tag types are returned by XPath union operator') - end - - - def test_a_star_star_one - string = <<-EOL - - - - - - - - - - - - - - - EOL - d = REXML::Document.new( string ) - c1 = XPath.match( d, '/a/*/*[1]' ) - assert_equal( 1, c1.length ) - assert_equal( 'c1', c1[0].name ) - end - - def test_sum - d = Document.new(""+ - "123"+ - "12"+ - ""+ - "") - - for v,p in [[6, "sum(/a/b)"], - [9, "sum(//b | //d)"], - [3, "sum(/a/e/@*)"] ] - assert_equal( v, XPath::match( d, p ).first ) - end - end - - def test_xpath_namespace - d = REXML::Document.new("xa") - x = d.root - num = 0 - x.each_element('tada') { num += 1 } - assert_equal(1, num) - end - - def test_ticket_39 - doc = REXML::Document.new( <<-EOL ) - - - - true - - Item 1 - - - Item 2 - Thu, 13 Oct 2005 19:59:00 +0000 - - - Item 3 - - - - EOL - root_node = XPath.first(doc, "rss") - assert_not_nil root_node - channel_node = XPath.first(root_node, "channel") - assert_not_nil channel_node - items = XPath.match(channel_node, "*") - assert_equal 4, items.size - items = XPath.match(channel_node, "item") - assert_equal 3, items.size # fails - end - - - def test_ticket_42 - source = "" - doc = Document.new(source) - bElem = Element.new('b') - doc.root.add_element(bElem) - doc.elements.each('//b[name(..) = "a"]') { |x| - assert_equal x,bElem - } - end - - def test_ticket_56 - namespaces = {'h' => 'http://www.w3.org/1999/xhtml'} - - finaldoc = REXML::Document.new(File.read(fixture_path('google.2.xml'))) - - column_headers = [] - - REXML::XPath.each(finaldoc, '//h:form[@action="ModifyCampaign"]//h:th', - namespaces) do |el| - node = REXML::XPath.first(el, 'h:a/text()', namespaces) - column_headers << (node ? node.value : nil) - end - column_headers.map! { |h| h.to_s.strip.chomp } - expected = ["", "", "Current Status", "Current Budget", - "Clicks", "Impr.", "CTR", "Avg. CPC", "Cost", "Conv. Rate", - "Cost/Conv."] - assert_equal( expected, column_headers ) - end - - - def test_ticket_70 - string = < - - Text1, text, -text - - Text2, text, -text - - - - -EOF - doc = Document.new string - assert_equal( 1, XPath.match( doc, "//someelement[contains(@attribute,'1.10')]" ).length ) - end - - def test_ticket_43 - #url = http://news.search.yahoo.com/news/rss?p=market&ei=UTF-8&fl=0&x=wrt - - sum = Document.new(File.new(fixture_path("yahoo.xml"))).elements.to_a("//item").size - assert_equal( 10, sum ) - - text = Document.new(File.new(fixture_path("yahoo.xml"))).elements.to_a(%Q{//title[contains(text(), "'")]}).collect{|e| e.text}.join - assert_equal( "Broward labor market's a solid performer (Miami Herald)", text ) - end - - def test_ticket_57 - data = "zzz" - - r = Document.new(data) - - assert_equal(Text, REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").class) - assert_equal("zzz", REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").to_s) - end - - def test_ticket_59 - data = " - - - - - - - - - - - - - - - - - - - - - - - - - - - " - d = Document.new(data) - res = d.elements.to_a( "//c" ).collect {|e| e.attributes['id'].to_i} - assert_equal( res, res.sort ) - end - - def ticket_61_fixture(doc, xpath) - matches = [] - doc.elements.each(xpath) do |element| - matches << element - assert_equal('Add', element.text) - assert_equal('ButtonText', element.attributes['class']) - end - assert_equal(1, matches.length) - end - - def test_ticket_61_text - file = File.open(fixture_path("ticket_61.xml")) - doc = REXML::Document.new file - ticket_61_fixture( doc, "//div[text()='Add' and @class='ButtonText']" ) - end - - def test_ticket_61_contains - file = File.open(fixture_path("ticket_61.xml")) - doc = REXML::Document.new file - ticket_61_fixture( doc, "//div[contains(.,'Add') and @class='ButtonText']" ) - end - - def test_namespaces_0 - d = Document.new(%q{}) - assert_equal( 1, XPath.match( d, "//x:a" ).size ) - assert_equal( 1, XPath.match( d, "//x:*" ).size ) - end - - def test_ticket_71 - doc = Document.new(%Q{}) - el = doc.root.elements[1] - assert_equal( "element", el.name ) - el2 = XPath.first( doc.root, "element[@ns:attrname='foo']", { 'ns' => "xyz" } ) - assert_equal( el, el2 ) - end - - def test_ticket_78 - doc = <<-EOT - - - 123 - - - 123a - - - EOT - seq = %w{BEGIN 123 END BEGIN 123a END} - - xmlDoc = Document.new(doc) - - ["//element[tag='123']/tag", "//element[tag='123a']/tag"].each do |query| - assert_equal( "BEGIN", seq.shift ) - XPath.each(xmlDoc, query) { |element| - assert_equal( seq.shift, element.text ) - } - assert_equal( "END", seq.shift ) - end - end - - def test_ticket_79 - source = "test3" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/a/b[c='test']} ) - assert_equal(1, r.size()) - r = REXML::XPath.match( d, %q{/a/b[c='3']} ) - assert_equal(1, r.size()) - end - - def test_or_and - doc = " - - - test - - -

- A link. -

- - -" - - xmldoc = REXML::Document.new(doc) - xpath = "descendant::node()[(local-name()='link' or local-name()='a') and @rel='sub']" - hrefs = [] - xmldoc.elements.each(xpath) do |element| - hrefs << element.attributes["href"] - end - assert_equal(["/"], hrefs, "Bug #3842 [ruby-core:32447]") - end -end diff --git a/test/rexml/test_xpath_attribute_query.rb b/test/rexml/test_xpath_attribute_query.rb deleted file mode 100644 index c0ad2c2e8c..0000000000 --- a/test/rexml/test_xpath_attribute_query.rb +++ /dev/null @@ -1,89 +0,0 @@ -# rexml_xpath_attribute_query.rb -# May 16, 2007 -# - -require 'test/unit' -require 'rexml/document' - -class TestRexmlXpathAttributeQuery < Test::Unit::TestCase - - # xmlstr1 and xmlstr2 only differ in the second line - namespaces in the root element - @@xmlstr1 = ' - - http://www.google.com/calendar/feeds/me%40gmail.com - - http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com - 2007-05-16T13:42:27.942Z - 2007-05-15T03:29:28.000Z - My Calendar - - - - - Me - me@gmail.com - - -' - - - @@xmlstr2 = ' - - http://www.google.com/calendar/feeds/me%40gmail.com - - http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com - 2007-05-16T13:42:27.942Z - 2007-05-15T03:29:28.000Z - My Calendar - - - - - Me - me@gmail.com - - -' - - # Fails - def test_xpath_query - do_test @@xmlstr1 - end - - # Passes - def test_xpath_query_no_namespace - do_test @@xmlstr2 - end - - def do_test(xmlString) - hrefs = [ - "http://www.google.com/calendar/feeds/me%40gmail.com/private/full", - "http://www.google.com/calendar/feeds/me%40gmail.com/acl/full", - "http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com" - ] - ctr=0 - REXML::Document.new(xmlString).elements.each("feed/entry") do |element| - @alternate_link = element.elements["link[@rel='alternate']"] - assert_not_nil( @alternate_link ) - assert_equal( hrefs[ctr], @alternate_link.attributes['href']) - ctr += 1 - end - end - - - def test_another_way - doc = REXML::Document.new(@@xmlstr1) - hrefs = [ - "http://www.google.com/calendar/feeds/me%40gmail.com/private/full", - "http://www.google.com/calendar/feeds/me%40gmail.com/acl/full", - "http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com" - ] - ctr=0 - REXML::XPath.each(doc, "//link[@rel='alternate']") do |element| - @alternate_link = element - assert_not_nil @alternate_link - assert_equal( hrefs[ctr], @alternate_link.attributes['href']) - ctr += 1 - end - end -end diff --git a/test/rexml/test_xpath_msw.rb b/test/rexml/test_xpath_msw.rb deleted file mode 100644 index d0b474faf5..0000000000 --- a/test/rexml/test_xpath_msw.rb +++ /dev/null @@ -1,38 +0,0 @@ -require "test/unit/testcase" -require "rexml/document" - -class XPathAxesTester < Test::Unit::TestCase - include REXML - SOURCE = <<-EOF - - - - - - - - - EOF - - def setup - @@doc = Document.new(SOURCE) unless defined? @@doc - end - - def test_preceding_sibling_axis - context = XPath.first(@@doc,"/a/e/f[last()]") - assert_equal "6", context.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f") - assert_equal "5", prev.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f[1]") - assert_equal "5", prev.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f[2]") - assert_equal "4", prev.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f[3]") - assert_equal "3", prev.attributes["id"] - end -end - diff --git a/test/rexml/test_xpath_pred.rb b/test/rexml/test_xpath_pred.rb deleted file mode 100644 index 584358966a..0000000000 --- a/test/rexml/test_xpath_pred.rb +++ /dev/null @@ -1,80 +0,0 @@ -require "test/unit/testcase" -require "rexml/document" -require "rexml/xpath" -require "rexml/parsers/xpathparser" - -class XPathPredicateTester < Test::Unit::TestCase - include REXML - SRC=<<-EOL -
-
- free flowing text. -
-
-
- free flowing text. -
-
- free flowing text. -
-
-
- EOL - - def setup - @doc = REXML::Document.new( SRC ) - @parser = REXML::Parsers::XPathParser.new - - end - - def test_predicates_parent - path = '//section[../self::section[@role="division"]]' - m = do_path( path ) - assert_equal( 2, m.size ) - assert_equal( "2", m[0].attributes["id"] ) - assert_nil( m[1].attributes["id"] ) - end - - def test_predicates_single - path = '//section[@role="subdivision" and not(../self::section[@role="division"])]' - m = do_path( path ) - assert_equal( 1, m.size ) - assert_equal( "1", m[0].attributes["id"] ) - end - - def test_predicates_multi - path = '//section[@role="subdivision"][not(../self::section[@role="division"])]' - m = do_path( path ) - assert_equal( 1, m.size ) - assert_equal( "1", m[0].attributes["id"] ) - end - - def do_path( path ) - m = REXML::XPath.match( @doc, path ) - #puts path, @parser.parse( path ).inspect - return m - end - - def test_get_no_siblings_terminal_nodes - source = <<-XML - - TEXT1 - - - - TEXT2 - - - -XML - doc = REXML::Document.new(source) - predicate = "count(child::node()|" + - "following-sibling::node()|" + - "preceding-sibling::node())=0" - m = REXML::XPath.match(doc, "/descendant-or-self::node()[#{predicate}]") - assert_equal( [REXML::Text.new("TEXT1"), - REXML::Text.new("TEXT2"), - REXML::Comment.new("COMMENT")], - m ) - end -end diff --git a/test/rexml/test_xpathtext.rb b/test/rexml/test_xpathtext.rb deleted file mode 100644 index 87441cb6d5..0000000000 --- a/test/rexml/test_xpathtext.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'test/unit' -require 'rexml/document' -require 'rexml/element' -require 'rexml/xpath' - -class XpathTestCase < Test::Unit::TestCase - def setup - @doc = REXML::Document.new - end - - def tear_down - end - - def test_text_as_element - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - REXML::Text.new('test', false, node2) - assert_equal(1, @doc.elements.size, "doc owns 1 element node1") - assert_same(node1, @doc.elements[1], "doc owns 1 element node1") - assert_equal(1, node1.elements.size, "node1 owns 1 element node2") - assert_same(node2, node1.elements[1], "node1 owns 1 element node2") - assert_equal(1, node2.size, "node2 owns 1 text element") - end - - def test_text_in_xpath_query - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - textnode = REXML::Text.new('test', false, node2) - textnode.parent = node2 # should be unnecessary - nodes = @doc.get_elements('//b') - assert_equal(1, nodes.size, "document has one element") - # why doesn't this query work right? - nodes = REXML::XPath.match(@doc, '//text()') - assert_equal(1, nodes.size, "//text() should yield one Text element") - assert_equal(REXML::Text, nodes[0].class) - end - - def test_comment_in_xpath_query - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - commentnode = REXML::Comment.new('test', node2) - nodes = REXML::XPath.match(@doc, '//comment()') - assert_equal(1, nodes.size, "//comment() should yield one Comment element") - assert_same commentnode, nodes[0] - end - - def test_parentage - node1 = REXML::Element.new('a', @doc) - assert_same(@doc, node1.parent, "node1 parent is document") - node2 = REXML::Element.new('b', node1) - assert_same(node1, node2.parent, "node2 parent is node1") - textnode = REXML::Text.new('test', false, node2) - # why isn't the text's parent node2? - # Also look at Comment, etc. - assert_same(node2, textnode.parent) - comment = REXML::Comment.new('Test comment', node2) - assert_same(node2, comment.parent) - end - - def test_ancestors - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - textnode = REXML::Text.new('test', false, node2) - #textnode.parent = node2 # should be unnecessary - assert_same node2, textnode.parent - nodes = @doc.get_elements('//b/ancestor::*') - assert_equal(1, nodes.size, " has one element ancestor") - nodes = @doc.get_elements('//b/ancestor::node()') - assert_equal(2, nodes.size, " has two node ancestors") - assert nodes[1].kind_of?(REXML::Document) - end -end diff --git a/test/rexml/xpath/test_attribute.rb b/test/rexml/xpath/test_attribute.rb new file mode 100644 index 0000000000..9af83a3081 --- /dev/null +++ b/test/rexml/xpath/test_attribute.rb @@ -0,0 +1,85 @@ +require 'test/unit' +require 'rexml/document' + +class TestXPathAttribute < Test::Unit::TestCase + + # xmlstr1 and xmlstr2 only differ in the second line - namespaces in the root element + @@xmlstr1 = ' + + http://www.google.com/calendar/feeds/me%40gmail.com + + http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com + 2007-05-16T13:42:27.942Z + 2007-05-15T03:29:28.000Z + My Calendar + + + + + Me + me@gmail.com + + +' + + + @@xmlstr2 = ' + + http://www.google.com/calendar/feeds/me%40gmail.com + + http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com + 2007-05-16T13:42:27.942Z + 2007-05-15T03:29:28.000Z + My Calendar + + + + + Me + me@gmail.com + + +' + + # Fails + def test_xpath_query + do_test @@xmlstr1 + end + + # Passes + def test_xpath_query_no_namespace + do_test @@xmlstr2 + end + + def do_test(xmlString) + hrefs = [ + "http://www.google.com/calendar/feeds/me%40gmail.com/private/full", + "http://www.google.com/calendar/feeds/me%40gmail.com/acl/full", + "http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com" + ] + ctr=0 + REXML::Document.new(xmlString).elements.each("feed/entry") do |element| + @alternate_link = element.elements["link[@rel='alternate']"] + assert_not_nil( @alternate_link ) + assert_equal( hrefs[ctr], @alternate_link.attributes['href']) + ctr += 1 + end + end + + + def test_another_way + doc = REXML::Document.new(@@xmlstr1) + hrefs = [ + "http://www.google.com/calendar/feeds/me%40gmail.com/private/full", + "http://www.google.com/calendar/feeds/me%40gmail.com/acl/full", + "http://www.google.com/calendar/feeds/me%40gmail.com/me%40gmail.com" + ] + ctr=0 + REXML::XPath.each(doc, "//link[@rel='alternate']") do |element| + @alternate_link = element + assert_not_nil @alternate_link + assert_equal( hrefs[ctr], @alternate_link.attributes['href']) + ctr += 1 + end + end +end diff --git a/test/rexml/xpath/test_axis_preceding_sibling.rb b/test/rexml/xpath/test_axis_preceding_sibling.rb new file mode 100644 index 0000000000..d2981b39cf --- /dev/null +++ b/test/rexml/xpath/test_axis_preceding_sibling.rb @@ -0,0 +1,38 @@ +require "test/unit/testcase" +require "rexml/document" + +class TestXPathAxisPredcedingSibling < Test::Unit::TestCase + include REXML + SOURCE = <<-EOF + + + + + + + + + EOF + + def setup + @@doc = Document.new(SOURCE) unless defined? @@doc + end + + def test_preceding_sibling_axis + context = XPath.first(@@doc,"/a/e/f[last()]") + assert_equal "6", context.attributes["id"] + + prev = XPath.first(context, "preceding-sibling::f") + assert_equal "5", prev.attributes["id"] + + prev = XPath.first(context, "preceding-sibling::f[1]") + assert_equal "5", prev.attributes["id"] + + prev = XPath.first(context, "preceding-sibling::f[2]") + assert_equal "4", prev.attributes["id"] + + prev = XPath.first(context, "preceding-sibling::f[3]") + assert_equal "3", prev.attributes["id"] + end +end + diff --git a/test/rexml/xpath/test_base.rb b/test/rexml/xpath/test_base.rb new file mode 100644 index 0000000000..26cd3f7ba7 --- /dev/null +++ b/test/rexml/xpath/test_base.rb @@ -0,0 +1,1079 @@ +require_relative "../rexml_test_utils" + +require "rexml/document" + +class TestXPathBase < Test::Unit::TestCase + include REXMLTestUtils + include REXML + SOURCE = <<-EOF + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + EOF + JENI_TENNISON = <<-EOJT + + + + + + + + + + + + + + + + + + + + + + + + EOJT + + def setup + @@doc = Document.new(SOURCE) unless defined? @@doc + @@jeni = Document.new( JENI_TENNISON ) unless defined? @@jeni + end + + def each_test( element, xpath ) + count = 0 + XPath::each( element, xpath ) { |child| + count += 1 + yield child if block_given? + } + count + end + + def test_descendant + doc = Document.new("") + p = XPath.match( doc, "//c" ) + assert_equal( 2, p.size ) + p = XPath.first( @@doc, "//p" ) + assert_equal "p", p.name + c = each_test( @@doc, "//c" ) { |child| assert_equal "c", child.name } + assert_equal 5, c + c = each_test( @@doc.root, "b//c" ) { |child| + assert_equal "c", child.name + } + assert_equal 2, c + + doc = Document.new( "" ) + # //para[1] : all descendants which are the first para child of their parent + assert_equal( 4, XPath.match( doc, "//z[1]" ).size ) + # /descendant::para[1] : the first descendant para element + assert_equal( 1, XPath.match( doc, "/descendant::z[1]" ).size ) + end + + def test_root + source = "" + doc = Document.new( source ) + assert_equal doc, doc.root_node + assert_equal "a", XPath::first( doc, "/" ).elements[1].name + end + + def test_abbreviated_simple_child + assert_equal "a", XPath::first(@@doc, "a").name + end + + def test_child + c = XPath::first( @@doc, "a/b/c" ) + assert_equal "c", c.name + assert_equal "3", XPath::first(@@doc, "a/b/c").attributes["id"] + end + + def test_root_child + assert_equal "a", XPath::first(@@doc, "/a").name + c = XPath::first( @@doc, "a/b/c" ) + assert_equal "a", XPath::first(c, "/a").name + end + + def test_root_children + c = XPath::first( @@doc, "a/b/c" ) + assert_equal "2", XPath::first(c, "/a/b").attributes["id"] + end + + def test_abbreviated_step + c = XPath::first( @@doc, "a/b/c" ) + assert_equal("c", c.name) + assert_equal("a", XPath::first(@@doc.root, ".").name) + assert_equal("b", XPath::first(c, "..").name) + assert_equal("a", XPath::first(@@doc, "a/b/..").name) + + doc = REXML::Document.new(File.new(fixture_path("project.xml"))) + c = each_test(doc.root, "./Description" ) { |child| + assert_equal("Description",child.name) + } + assert_equal 1, c + end + + # Things that aren't tested elsewhere + def test_predicates + assert_equal "12", XPath::first(@@doc, "a/e/f[3]").attributes["id"] + assert_equal "13", XPath::first(@@doc, "a/e/f[3]/g").attributes["id"] + assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][2]").attributes["id"] + assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][@id='14']").attributes["id"] + assert_equal "a", XPath::first( @@doc, "*[name()='a' and @id='1']" ).name + c=each_test( @@doc, "//*[name()='f' and @a='d']") { |i| + assert_equal "f", i.name + } + assert_equal 2, c + c=each_test( @@doc, "//*[name()='m' or @a='d']") { |i| + assert ["m","f"].include?(i.name) + } + assert_equal 3, c + + assert_equal "b", XPath::first( @@doc, "//b[@x]" ).name + end + + def test_node_type + doc = Document.new "text" + #res = XPath::first(doc.root, "text()") + #assert_equal "text", res.to_s + + #res = XPath::first(doc, "*") + #assert_equal "a", res.name + + assert_equal( :processing_instruction, + XPath::first(doc.root, "processing-instruction()").node_type) + assert_equal( :comment, XPath::first(doc.root, "comment()").node_type) + end + + def test_functions + # trivial text() test + # confuse-a-function + source = "more dumb text" + doc = Document.new source + res = "" + #XPath::each(doc.root, "text()") {|val| res << val.to_s} + #assert_equal "more text", res + + #res = XPath::first(doc.root, "b[last()]") + #assert_equal '3', res.attributes['id'] + res = XPath::first(doc.root, "b[position()=2]") + assert_equal '2', res.attributes['id'] + res = XPath::first(doc.root, "*[name()='c']") + assert_equal "c", res.name + end + + def no_test_ancestor + doc = REXML::Document.new(File.new(fixture_path("testsrc.xml"))) + doc.elements.each("//item") { |el| print el.name + if el.attributes['x'] + puts " -- "+el.attributes['x'] + else + puts + end + } + doc.elements.each("//item/ancestor::") { |el| print el.name + if el.attributes['x'] + puts " -- "+el.attributes['x'] + else + puts + end + } + end + + # Here are some XPath tests that were originally submitted by ... + # The code has changed some, but the logic and the source documents are the + # same. + # This method reads a document from a file, and then a series of xpaths, + # also from a file. It then checks each xpath against the source file. + def test_more + xmlsource = fixture_path("testsrc.xml") + xpathtests = fixture_path("xp.tst") + + doc = REXML::Document.new(File.new(xmlsource)) + #results = "" + results = REXML::Document.new + results.add_element "test-results" + for line in File.new(xpathtests) + line.strip! + begin + doc.root + #puts "#"*80 + #print "\nDoing #{line} " ; $stdout.flush + doc.elements.each(line) do |el| + #print "." ; $stdout.flush + results.root << el.clone + #results << el.to_s + end + #ObjectSpace.garbage_collect + GC::start + rescue Exception => z + #puts "\n'#{line}' failed" + fail("Error on line #{line}:\n#{z.message}\n"+z.backtrace[0,10].join("\n")) + #results.root.add_element( "error", {"path"=>line}).text = z.message+"\n"+z.backtrace[0,10].join("\n") + #results << ""+z.message+"" + end + end + end + + def test_axe_descendant + assert_equal "f", XPath::first( @@doc, "descendant::f").name + end + + def test_axe_parent + q = XPath.first( @@doc, "a/d/c/parent::*/q" ) + assert_equal 19, q.attributes["id"].to_i + end + + def test_abbreviated_attribute + assert_equal 'a', XPath::first( @@doc, "a[@id='1']" ).name + c = XPath::first( @@doc, "a/b/c[@id='4']" ) + assert_equal 'c', c.name + assert_equal '4', c.attributes['id'] + + result = XPath::first( @@doc, "descendant::f[@a='c']") + assert_equal "11", result.attributes['id'] + + assert_equal "11", XPath::first(@@doc, "a/e/f[@a='c']").attributes["id"] + assert_equal "11", XPath::first(@@doc, "a/e/*[@a='c']").attributes["id"] + end + + def test_axe_self + c = XPath::first( @@doc, "a/b/c" ) + assert c + assert_equal "c", c.name + assert_equal "c", XPath::first( c, "self::node()" ).name + end + + def test_axe_ancestor + doc = REXML::Document.new " + + + + + + + + + " + + d = XPath.first( doc, "//d" ) + assert_equal "d", d.name + b = each_test( d, "ancestor::b" ) { |el| + assert((1..2) === el.attributes['id'].to_i, + "Expected #{el.attributes['id']} to be either 1 or 2" + ) + } + assert_equal 2, b + end + + def test_axe_child + m = XPath.first( @@doc, "a/child::m" ) + assert_equal 15, m.attributes['id'].to_i + end + + def test_axe_attribute + a = XPath.first( @@doc, "a/attribute::id" ) + assert_equal "1", a.value + a = XPath.first( @@doc, "a/e/f[@id='14']/attribute::a" ) + assert_equal "d", a.value + end + + def test_axe_sibling + doc = Document.new "" + first_f = XPath.first( doc, "a/e/f" ) + assert first_f + assert_equal '10', first_f.attributes['id'] + next_f = XPath.first( doc, "a/e/f/following-sibling::node()" ) + assert_equal '11', next_f.attributes['id'] + + b = XPath.first( doc, "a/e/preceding-sibling::node()" ) + assert_equal 'b', b.name + end + + def test_lang + doc = Document.new(File.new(fixture_path("lang0.xml"))) + #puts IO.read( "test/lang.xml" ) + + #puts XPath.match( doc, "//language/*" ).size + c = each_test( doc, "//language/*" ) { |element| + #puts "#{element.name}: #{element.text}" + } + assert_equal 4, c + end + + def test_namespaces_1 + source = <<-EOF + + this bar + that bar + + EOF + doc = Document.new source + XPath.each( doc, "//bar" ) { + fail "'bar' should match nothing in this case" + } + + namespace = {"t"=>"this"} + results = XPath.first( doc, "//t:bar", namespace ) + assert_equal "this bar", results.text + end + + def test_namespaces_2 + source = <<-EOF + + this bar + that bar + + EOF + doc = Document.new source + res = XPath::first(doc, "//*[local_name()='bar']") + assert res, "looking for //*[name()='bar']" + assert_equal 'this', res.namespace + res = XPath::first(doc.root, "*[namespace_uri()='that']") + assert_equal 'that bar', res.text + end + + def test_complex + next_f = XPath.first( @@doc, "a/e/f[@id='11']/following-sibling::*" ) + assert_equal 12, next_f.attributes['id'].to_i + prev_f = XPath.first( @@doc, "a/e/f[@id='11']/preceding-sibling::*" ) + assert_equal 10, prev_f.attributes['id'].to_i + c = each_test( @@doc, "descendant-or-self::*[@x='y']" ) + assert_equal 2, c + end + + def test_grouping + t = XPath.first( @@doc, "a/d/*[name()='d' and (name()='f' or name()='q')]" ) + assert_nil t + t = XPath.first( @@doc, "a/d/*[(name()='d' and name()='f') or name()='q']" ) + assert_equal 'q', t.name + end + + def test_preceding + d = Document.new "" + start = XPath.first( d, "/a/b[@id='1']" ) + assert_equal 'b', start.name + c = XPath.first( start, "preceding::c" ) + assert_equal '2', c.attributes['id'] + + c1, c0 = XPath.match( d, "/a/b/c[@id='2']/preceding::node()" ) + assert_equal '1', c1.attributes['id'] + assert_equal '0', c0.attributes['id'] + + c2, c1, c0, b, b2, b0 = XPath.match( start, "preceding::node()" ) + + assert_equal 'c', c2.name + assert_equal 'c', c1.name + assert_equal 'c', c0.name + assert_equal 'b', b.name + assert_equal 'b', b2.name + assert_equal 'b', b0.name + + assert_equal '2', c2.attributes['id'] + assert_equal '1', c1.attributes['id'] + assert_equal '0', c0.attributes['id'] + assert b.attributes.empty? + assert_equal '2', b2.attributes['id'] + assert_equal '0', b0.attributes['id'] + + d = REXML::Document.new("") + matches = REXML::XPath.match(d, "/a/d/preceding::node()") + assert_equal("c", matches[0].name) + assert_equal("b", matches[1].name) + + s = "" + d = REXML::Document.new(s) + c = REXML::XPath.match( d, "//c[@id = '5']") + cs = REXML::XPath.match( c, "preceding::c" ) + assert_equal( 4, cs.length ) + end + + def test_following + d = Document.new "" + start = XPath.first( d, "/a/b[@id='0']" ) + assert_equal 'b', start.name + c = XPath.first( start, "following::c" ) + assert_equal '1', c.attributes['id'] + + s = "" + d = Document.new(s) + c = XPath.first(d, '/a/b/c') + assert_equal 'c', c.name + res = XPath.match( c, 'following::*' ) + assert_equal 6, res.size + res = XPath.match( c, 'following::i' ) + assert_equal 2, res.size + end + + # The following three paths were provided by + # Jeni Tennison + # a consultant who is also an XSL and XPath expert + #def test_child_cubed + # els = @@jeni.elements.to_a("*****") + # assert_equal 3, els.size + #end + + #def test_div_2 + # results = doc.elements.to_a("/ div 2") + #end + + #def test_nested_predicates + # puts @@jeni.root.elements[1].elements[1].name + # results = @@jeni.root.elements[1].elements[1].elements.to_a("../following-sibling::*[*[name() = name(current())]]") + # puts results + #end + + # Contributed by Mike Stok + def test_starts_with + source = <<-EOF + + a@b.c + http://www.foo.com + + EOF + doc = Document.new source + mailtos = doc.elements.to_a("//a[starts-with(@href, 'mailto:')]") + assert_equal 1, mailtos.size + assert_equal "mailto:a@b.c", mailtos[0].attributes['href'] + + ailtos = doc.elements.to_a("//a[starts-with(@href, 'ailto:')]") + assert_equal 0, ailtos.size + end + + def test_toms_text_node + file = "ABCDEF" + doc = Document.new(file) + assert_equal 'A', XPath.first(doc[0], 'text()').to_s + assert_equal 'AF', XPath.match(doc[0], 'text()').collect { |n| + n.to_s + }.join('') + assert_equal 'B', XPath.first(doc[0], 'b/text()').to_s + assert_equal 'D', XPath.first(doc[0], '//d/text()').to_s + assert_equal 'ABCDEF', XPath.match(doc[0], '//text()').collect {|n| + n.to_s + }.join('') + end + + def test_string_length + doc = Document.new <<-EOF + + + + + + + + + EOF + assert doc, "create doc" + + set = doc.elements.to_a("//*[string-length(name()) = 3]") + assert_equal 2, set.size, "nodes with names length = 3" + + set = doc.elements.to_a("//*[string-length(name()) < 3]") + assert_equal 2, set.size, "nodes with names length < 3" + + set = doc.elements.to_a("//*[string-length(name()) > 3]") + assert_equal 3, set.size, "nodes with names length > 3" + end + + # Test provided by Mike Stok + def test_contains + source = <<-EOF + + a@b.c + http://www.foo.com + + EOF + doc = Document.new source + + [ + #['o', 2], + ['foo', 1], ['bar', 0]].each { |search, expected| + set = doc.elements.to_a("//a[contains(@href, '#{search}')]") + assert_equal expected, set.size + } + end + + # Mike Stok and Sean Russell + def test_substring + # examples from http://www.w3.org/TR/xpath#function-substring + doc = Document.new('') + + Document.new("") + #puts XPath.first(d, 'node()[0 + 1]') + #d = Document.new("") + #puts XPath.first(d, 'a[0 mod 0]') + [ [1.5, 2.6, '234'], + [0, 3, '12'], + [0, '0 div 0', ''], + [1, '0 div 0', ''], + ['-42', '1 div 0', '12345'], + ['-1 div 0', '1 div 0', ''] + ].each { |start, length, expected| + set = doc.elements.to_a("//test[substring(@string, #{start}, #{length}) = '#{expected}']") + assert_equal 1, set.size, "#{start}, #{length}, '#{expected}'" + } + end + + def test_translate + source = <<-EOF + + + + + + + + EOF + + doc = Document.new(source) + + [ ['bar', 'abc', 'ABC', 'w3c one'], + ['--aaa--','abc-','ABC', 'w3c two'], + ['lead', 'dear language', 'doll groover', 'alchemy'], + ['A Space Odissei', 'i', 'y', 'vbxml one'], + ['abcdefg', 'aceg', 'ACE', 'vbxml two'], + ].each { |arg1, arg2, arg3, name| + translate = "translate('#{arg1}', '#{arg2}', '#{arg3}')" + set = doc.elements.to_a("//case[@result = #{translate}]") + assert_equal 1, set.size, translate + assert_equal name, set[0].attributes['name'] + } + end + + def test_math + d = Document.new( '' ) + assert XPath.first( d.root, 'node()[1]' ) + assert_equal 'b', XPath.first( d.root, 'node()[1]' ).name + assert XPath.first( d.root, 'node()[0 + 1]' ) + assert_equal 'b', XPath.first( d.root, './node()[0 + 1]' ).name + assert XPath.first( d.root, 'node()[1 + 1]' ) + assert_equal 'c', XPath.first( d.root, './node()[1 + 1]' ).name + assert XPath.first( d.root, 'node()[4 div 2]' ) + assert_equal 'c', XPath.first( d.root, './node()[4 div 2]' ).name + assert XPath.first( d.root, 'node()[2 - 1]' ) + assert_equal 'b', XPath.first( d.root, './node()[2 - 1]' ).name + assert XPath.first( d.root, 'node()[5 mod 2]' ) + assert_equal 'b', XPath.first( d.root, './node()[5 mod 2]' ).name + assert XPath.first( d.root, 'node()[8 mod 3]' ) + assert_equal 'c', XPath.first( d.root, './node()[8 mod 3]' ).name + assert XPath.first( d.root, 'node()[1 * 2]' ) + assert_equal 'c', XPath.first( d.root, './node()[1 * 2]' ).name + assert XPath.first( d.root, 'node()[2 + -1]' ) + assert_equal 'b', XPath.first( d.root, './node()[2 + -1]' ).name + end + + def test_name + assert_raise( UndefinedNamespaceException, "x should be undefined" ) { + REXML::Document.new("") + } + d = REXML::Document.new("") + assert_equal 1, d.root.elements.to_a('*[name() = "b"]').size + assert_equal 1, d.elements.to_a('//*[name() = "x:b"]').size + end + + def test_local_name + d = REXML::Document.new("") + assert_equal 2, d.root.elements.to_a('*[local_name() = "b"]').size + assert_equal 2, d.elements.to_a('//*[local_name() = "b"]').size + end + + def test_comparisons + source = "" + doc = REXML::Document.new(source) + + # NOTE TO SER: check that number() is required + assert_equal 2, REXML::XPath.match(doc, "//b[number(@id) > 1]").size + assert_equal 3, REXML::XPath.match(doc, "//b[number(@id) >= 1]").size + assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) <= 1]").size + assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 * 1)]").size + assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 mod 2)]").size + assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (4 div 2)]").size + end + + # Contributed by Kouhei + def test_substring_before + doc = Document.new("") + assert_equal("a", doc.root.elements.to_a("*[name()=substring-before('abc', 'b')]")[0].name) + assert_equal("c", doc.root.elements.to_a("*[name()=substring-after('abc', 'b')]")[0].name) + end + + def test_spaces + doc = Document.new(" + + + + + ") + assert_equal( 1, REXML::XPath.match(doc, + "//*[local-name()='c' and @id='b']").size ) + assert_equal( 1, REXML::XPath.match(doc, + "//*[ local-name()='c' and @id='b' ]").size ) + assert_equal( 1, REXML::XPath.match(doc, + "//*[ local-name() = 'c' and @id = 'b' ]").size ) + assert_equal( 1, + REXML::XPath.match(doc, '/a/c[@id]').size ) + assert_equal( 1, + REXML::XPath.match(doc, '/a/c[(@id)]').size ) + assert_equal( 1, + REXML::XPath.match(doc, '/a/c[ @id ]').size ) + assert_equal( 1, + REXML::XPath.match(doc, '/a/c[ (@id) ]').size ) + assert_equal( 1, + REXML::XPath.match(doc, '/a/c[( @id )]').size ) + assert_equal( 1, REXML::XPath.match(doc.root, + '/a/c[ ( @id ) ]').size ) + assert_equal( 1, REXML::XPath.match(doc, + '/a/c [ ( @id ) ] ').size ) + assert_equal( 1, REXML::XPath.match(doc, + ' / a / c [ ( @id ) ] ').size ) + end + + def test_text_nodes + # source = " + # + #test + #" + source = "test" + d = REXML::Document.new( source ) + r = REXML::XPath.match( d, %q{/root/child[text()="test"]} ) + assert_equal( 1, r.size ) + assert_equal( "child", r[0].name ) + assert_equal( "test", r[0].text ) + end + + def test_auto_string_value + source = "Introduction" + d = REXML::Document.new( source ) + #r = REXML::XPath.match( d, %q{/root[title="Introduction"]} ) + #assert_equal( 1, r.size ) + source = "test" + d = REXML::Document.new( source ) + r = REXML::XPath.match( d, %q{/a[c='test']} ) + assert_equal( 1, r.size ) + r = REXML::XPath.match( d, %q{a[c='test']} ) + assert_equal( 1, r.size ) + r = d.elements["/a[c='test']"] + assert_not_nil( r ) + r = d.elements["a[c='test']"] + assert_not_nil( r ) + r = d.elements["a[c='xtest']"] + assert_nil( r ) + r = REXML::XPath.match( d, %q{a[c='xtest']} ) + assert_equal( 0, r.size ) + end + + def test_ordering + source = "" + d = REXML::Document.new( source ) + r = REXML::XPath.match( d, %q{/a/*/*[1]} ) + assert_equal( 1, r.size ) + r.each { |el| assert_equal( '1', el.attribute('id').value ) } + end + + def test_descendant_or_self_ordering + source = " + + + + + + + + + + + + + + + " + d = REXML::Document.new( source ) + cs = XPath.match( d, "/descendant-or-self::c" ) + assert_equal( 4, cs.length ) + 1.upto(4) {|x| assert_equal( x.to_s, cs[x-1].attributes['id'] ) } + end + + def test_and + d = Document.new %q{} + assert_equal( nil, d.root.elements["route[@run='0']"] ) + assert_equal( nil, d.root.elements["route[@run='0' and @title='HNO']"] ) + end + + + def test_numbers + d = Document.new %q{} + + xp1 = "/a[ @x = 0 ]" + xp2 = "/a[ @x = '0' ]" + xp3 = "/a[ (@x + 1) = 1 ]" + xp4 = "/a[ @y = 0 ]" + xp5 = "/a[ (@z + 1) = 5 ]" + xp6 = "/a[ (@w + 1) = 5 ]" + xp7 = "/a[ (@v + 1) = 1 ]" + xp8 = "/a[ @n = 0 ]" + + assert_equal( 1, XPath.match( d, xp1 ).length ) + assert_equal( 1, XPath.match( d, xp2 ).length ) + assert_equal( 1, XPath.match( d, xp3 ).length ) + assert_equal( 0, XPath.match( d, xp4 ).length ) + assert_equal( 0, XPath.match( d, xp5 ).length ) + assert_equal( 0, XPath.match( d, xp6 ).length ) + assert_equal( 0, XPath.match( d, xp7 ).length ) + assert_equal( 0, XPath.match( d, xp8 ).length ) + end + + def test_tobis_preceding + doc_string = ' + + + + + +' + + doc = Document.new(doc_string) + + # e = REXML::XPath.first(doc,'/a/c/e') + e = doc.root.get_elements('/a/c/e')[0] + assert_equal( 1, e.get_elements('preceding-sibling::*').length ) + assert_equal( 2, XPath.match(e, 'preceding::*').length ) + end + + + def test_filtering + #doc=Document.new("") + #assert_equal( 3, XPath.match( doc, '/a/b/*[1]' ).length ) + #assert_equal( 2, XPath.match( doc, '/a/b/following-sibling::*[1]' ).length ) + end + + # Submitted by Alex + def test_union + data = %Q{

+ + a + + b +
} + rd = REXML::Document.new( data ) + #union = rd.get_elements("/div/span | /div/em") + #assert_equal(2, union.length, "/div/span | /div/em" ) + union = rd.get_elements('//*[name()="em" or name()="strong"]') + assert_equal(2, union.length, 'name() and "or" failed') + union = rd.get_elements('//em|//strong') + assert_equal(2, union.length, + 'Both tag types are returned by XPath union operator') + end + + + def test_union2 + src = <<-EOL +
+ +a + +b +
+ EOL + rd = REXML::Document.new( src ) + union = rd.get_elements('//em|//strong') + assert_equal(2, union.length, + 'Both tag types are returned by XPath union operator') + end + + + def test_a_star_star_one + string = <<-EOL + + + + + + + + + + + + + + + EOL + d = REXML::Document.new( string ) + c1 = XPath.match( d, '/a/*/*[1]' ) + assert_equal( 1, c1.length ) + assert_equal( 'c1', c1[0].name ) + end + + def test_sum + d = Document.new(""+ + "123"+ + "12"+ + ""+ + "") + + for v,p in [[6, "sum(/a/b)"], + [9, "sum(//b | //d)"], + [3, "sum(/a/e/@*)"] ] + assert_equal( v, XPath::match( d, p ).first ) + end + end + + def test_xpath_namespace + d = REXML::Document.new("xa") + x = d.root + num = 0 + x.each_element('tada') { num += 1 } + assert_equal(1, num) + end + + def test_ticket_39 + doc = REXML::Document.new( <<-EOL ) + + + + true + + Item 1 + + + Item 2 + Thu, 13 Oct 2005 19:59:00 +0000 + + + Item 3 + + + + EOL + root_node = XPath.first(doc, "rss") + assert_not_nil root_node + channel_node = XPath.first(root_node, "channel") + assert_not_nil channel_node + items = XPath.match(channel_node, "*") + assert_equal 4, items.size + items = XPath.match(channel_node, "item") + assert_equal 3, items.size # fails + end + + + def test_ticket_42 + source = "" + doc = Document.new(source) + bElem = Element.new('b') + doc.root.add_element(bElem) + doc.elements.each('//b[name(..) = "a"]') { |x| + assert_equal x,bElem + } + end + + def test_ticket_56 + namespaces = {'h' => 'http://www.w3.org/1999/xhtml'} + + finaldoc = REXML::Document.new(File.read(fixture_path('google.2.xml'))) + + column_headers = [] + + REXML::XPath.each(finaldoc, '//h:form[@action="ModifyCampaign"]//h:th', + namespaces) do |el| + node = REXML::XPath.first(el, 'h:a/text()', namespaces) + column_headers << (node ? node.value : nil) + end + column_headers.map! { |h| h.to_s.strip.chomp } + expected = ["", "", "Current Status", "Current Budget", + "Clicks", "Impr.", "CTR", "Avg. CPC", "Cost", "Conv. Rate", + "Cost/Conv."] + assert_equal( expected, column_headers ) + end + + + def test_ticket_70 + string = < + + Text1, text, +text + + Text2, text, +text + + + + +EOF + doc = Document.new string + assert_equal( 1, XPath.match( doc, "//someelement[contains(@attribute,'1.10')]" ).length ) + end + + def test_ticket_43 + #url = http://news.search.yahoo.com/news/rss?p=market&ei=UTF-8&fl=0&x=wrt + + sum = Document.new(File.new(fixture_path("yahoo.xml"))).elements.to_a("//item").size + assert_equal( 10, sum ) + + text = Document.new(File.new(fixture_path("yahoo.xml"))).elements.to_a(%Q{//title[contains(text(), "'")]}).collect{|e| e.text}.join + assert_equal( "Broward labor market's a solid performer (Miami Herald)", text ) + end + + def test_ticket_57 + data = "zzz" + + r = Document.new(data) + + assert_equal(Text, REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").class) + assert_equal("zzz", REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").to_s) + end + + def test_ticket_59 + data = " + + + + + + + + + + + + + + + + + + + + + + + + + + + " + d = Document.new(data) + res = d.elements.to_a( "//c" ).collect {|e| e.attributes['id'].to_i} + assert_equal( res, res.sort ) + end + + def ticket_61_fixture(doc, xpath) + matches = [] + doc.elements.each(xpath) do |element| + matches << element + assert_equal('Add', element.text) + assert_equal('ButtonText', element.attributes['class']) + end + assert_equal(1, matches.length) + end + + def test_ticket_61_text + file = File.open(fixture_path("ticket_61.xml")) + doc = REXML::Document.new file + ticket_61_fixture( doc, "//div[text()='Add' and @class='ButtonText']" ) + end + + def test_ticket_61_contains + file = File.open(fixture_path("ticket_61.xml")) + doc = REXML::Document.new file + ticket_61_fixture( doc, "//div[contains(.,'Add') and @class='ButtonText']" ) + end + + def test_namespaces_0 + d = Document.new(%q{}) + assert_equal( 1, XPath.match( d, "//x:a" ).size ) + assert_equal( 1, XPath.match( d, "//x:*" ).size ) + end + + def test_ticket_71 + doc = Document.new(%Q{}) + el = doc.root.elements[1] + assert_equal( "element", el.name ) + el2 = XPath.first( doc.root, "element[@ns:attrname='foo']", { 'ns' => "xyz" } ) + assert_equal( el, el2 ) + end + + def test_ticket_78 + doc = <<-EOT + + + 123 + + + 123a + + + EOT + seq = %w{BEGIN 123 END BEGIN 123a END} + + xmlDoc = Document.new(doc) + + ["//element[tag='123']/tag", "//element[tag='123a']/tag"].each do |query| + assert_equal( "BEGIN", seq.shift ) + XPath.each(xmlDoc, query) { |element| + assert_equal( seq.shift, element.text ) + } + assert_equal( "END", seq.shift ) + end + end + + def test_ticket_79 + source = "test3" + d = REXML::Document.new( source ) + r = REXML::XPath.match( d, %q{/a/b[c='test']} ) + assert_equal(1, r.size()) + r = REXML::XPath.match( d, %q{/a/b[c='3']} ) + assert_equal(1, r.size()) + end + + def test_or_and + doc = " + + + test + + +

+ A link. +

+ + +" + + xmldoc = REXML::Document.new(doc) + xpath = "descendant::node()[(local-name()='link' or local-name()='a') and @rel='sub']" + hrefs = [] + xmldoc.elements.each(xpath) do |element| + hrefs << element.attributes["href"] + end + assert_equal(["/"], hrefs, "Bug #3842 [ruby-core:32447]") + end +end diff --git a/test/rexml/xpath/test_predicate.rb b/test/rexml/xpath/test_predicate.rb new file mode 100644 index 0000000000..5c196b941b --- /dev/null +++ b/test/rexml/xpath/test_predicate.rb @@ -0,0 +1,80 @@ +require "test/unit/testcase" +require "rexml/document" +require "rexml/xpath" +require "rexml/parsers/xpathparser" + +class TestXPathPredicate < Test::Unit::TestCase + include REXML + SRC=<<-EOL +
+
+ free flowing text. +
+
+
+ free flowing text. +
+
+ free flowing text. +
+
+
+ EOL + + def setup + @doc = REXML::Document.new( SRC ) + @parser = REXML::Parsers::XPathParser.new + + end + + def test_predicates_parent + path = '//section[../self::section[@role="division"]]' + m = do_path( path ) + assert_equal( 2, m.size ) + assert_equal( "2", m[0].attributes["id"] ) + assert_nil( m[1].attributes["id"] ) + end + + def test_predicates_single + path = '//section[@role="subdivision" and not(../self::section[@role="division"])]' + m = do_path( path ) + assert_equal( 1, m.size ) + assert_equal( "1", m[0].attributes["id"] ) + end + + def test_predicates_multi + path = '//section[@role="subdivision"][not(../self::section[@role="division"])]' + m = do_path( path ) + assert_equal( 1, m.size ) + assert_equal( "1", m[0].attributes["id"] ) + end + + def do_path( path ) + m = REXML::XPath.match( @doc, path ) + #puts path, @parser.parse( path ).inspect + return m + end + + def test_get_no_siblings_terminal_nodes + source = <<-XML + + TEXT1 + + + + TEXT2 + + + +XML + doc = REXML::Document.new(source) + predicate = "count(child::node()|" + + "following-sibling::node()|" + + "preceding-sibling::node())=0" + m = REXML::XPath.match(doc, "/descendant-or-self::node()[#{predicate}]") + assert_equal( [REXML::Text.new("TEXT1"), + REXML::Text.new("TEXT2"), + REXML::Comment.new("COMMENT")], + m ) + end +end diff --git a/test/rexml/xpath/test_text.rb b/test/rexml/xpath/test_text.rb new file mode 100644 index 0000000000..c6a8691f55 --- /dev/null +++ b/test/rexml/xpath/test_text.rb @@ -0,0 +1,72 @@ +require 'test/unit' +require 'rexml/document' +require 'rexml/element' +require 'rexml/xpath' + +class TestXPathText < Test::Unit::TestCase + def setup + @doc = REXML::Document.new + end + + def tear_down + end + + def test_text_as_element + node1 = REXML::Element.new('a', @doc) + node2 = REXML::Element.new('b', node1) + REXML::Text.new('test', false, node2) + assert_equal(1, @doc.elements.size, "doc owns 1 element node1") + assert_same(node1, @doc.elements[1], "doc owns 1 element node1") + assert_equal(1, node1.elements.size, "node1 owns 1 element node2") + assert_same(node2, node1.elements[1], "node1 owns 1 element node2") + assert_equal(1, node2.size, "node2 owns 1 text element") + end + + def test_text_in_xpath_query + node1 = REXML::Element.new('a', @doc) + node2 = REXML::Element.new('b', node1) + textnode = REXML::Text.new('test', false, node2) + textnode.parent = node2 # should be unnecessary + nodes = @doc.get_elements('//b') + assert_equal(1, nodes.size, "document has one element") + # why doesn't this query work right? + nodes = REXML::XPath.match(@doc, '//text()') + assert_equal(1, nodes.size, "//text() should yield one Text element") + assert_equal(REXML::Text, nodes[0].class) + end + + def test_comment_in_xpath_query + node1 = REXML::Element.new('a', @doc) + node2 = REXML::Element.new('b', node1) + commentnode = REXML::Comment.new('test', node2) + nodes = REXML::XPath.match(@doc, '//comment()') + assert_equal(1, nodes.size, "//comment() should yield one Comment element") + assert_same commentnode, nodes[0] + end + + def test_parentage + node1 = REXML::Element.new('a', @doc) + assert_same(@doc, node1.parent, "node1 parent is document") + node2 = REXML::Element.new('b', node1) + assert_same(node1, node2.parent, "node2 parent is node1") + textnode = REXML::Text.new('test', false, node2) + # why isn't the text's parent node2? + # Also look at Comment, etc. + assert_same(node2, textnode.parent) + comment = REXML::Comment.new('Test comment', node2) + assert_same(node2, comment.parent) + end + + def test_ancestors + node1 = REXML::Element.new('a', @doc) + node2 = REXML::Element.new('b', node1) + textnode = REXML::Text.new('test', false, node2) + #textnode.parent = node2 # should be unnecessary + assert_same node2, textnode.parent + nodes = @doc.get_elements('//b/ancestor::*') + assert_equal(1, nodes.size, " has one element ancestor") + nodes = @doc.get_elements('//b/ancestor::node()') + assert_equal(2, nodes.size, " has two node ancestors") + assert nodes[1].kind_of?(REXML::Document) + end +end -- cgit v1.2.3