| 1 | require "test/unit/testcase" |
|---|
| 2 | require "rexml/document" |
|---|
| 3 | require "rexml/xpath" |
|---|
| 4 | require "rexml/parsers/xpathparser" |
|---|
| 5 | |
|---|
| 6 | class XPathPredicateTester < Test::Unit::TestCase |
|---|
| 7 | include REXML |
|---|
| 8 | SRC=<<-EOL |
|---|
| 9 | <article> |
|---|
| 10 | <section role="subdivision" id="1"> |
|---|
| 11 | <para>free flowing text.</para> |
|---|
| 12 | </section> |
|---|
| 13 | <section role="division"> |
|---|
| 14 | <section role="subdivision" id="2"> |
|---|
| 15 | <para>free flowing text.</para> |
|---|
| 16 | </section> |
|---|
| 17 | <section role="division"> |
|---|
| 18 | <para>free flowing text.</para> |
|---|
| 19 | </section> |
|---|
| 20 | </section> |
|---|
| 21 | </article> |
|---|
| 22 | EOL |
|---|
| 23 | |
|---|
| 24 | def setup |
|---|
| 25 | @doc = REXML::Document.new( SRC ) |
|---|
| 26 | @parser = REXML::Parsers::XPathParser.new |
|---|
| 27 | |
|---|
| 28 | end |
|---|
| 29 | |
|---|
| 30 | def test_predicates_parent |
|---|
| 31 | path = '//section[../self::section[@role="division"]]' |
|---|
| 32 | m = do_path( path ) |
|---|
| 33 | assert_equal( 2, m.size ) |
|---|
| 34 | assert_equal( "2", m[0].attributes["id"] ) |
|---|
| 35 | assert_nil( m[1].attributes["id"] ) |
|---|
| 36 | end |
|---|
| 37 | |
|---|
| 38 | def test_predicates_single |
|---|
| 39 | path = '//section[@role="subdivision" and not(../self::section[@role="division"])]' |
|---|
| 40 | m = do_path( path ) |
|---|
| 41 | assert_equal( 1, m.size ) |
|---|
| 42 | assert_equal( "1", m[0].attributes["id"] ) |
|---|
| 43 | end |
|---|
| 44 | |
|---|
| 45 | def test_predicates_multi |
|---|
| 46 | path = '//section[@role="subdivision"][not(../self::section[@role="division"])]' |
|---|
| 47 | m = do_path( path ) |
|---|
| 48 | assert_equal( 1, m.size ) |
|---|
| 49 | assert_equal( "1", m[0].attributes["id"] ) |
|---|
| 50 | end |
|---|
| 51 | |
|---|
| 52 | def do_path( path ) |
|---|
| 53 | m = REXML::XPath.match( @doc, path ) |
|---|
| 54 | #puts path, @parser.parse( path ).inspect |
|---|
| 55 | return m |
|---|
| 56 | end |
|---|
| 57 | |
|---|
| 58 | def test_get_no_siblings_terminal_nodes |
|---|
| 59 | source = <<-XML |
|---|
| 60 | <a> |
|---|
| 61 | <b number='1' str='abc'>TEXT1</b> |
|---|
| 62 | <c number='1'/> |
|---|
| 63 | <c number='2' str='def'> |
|---|
| 64 | <b number='3'/> |
|---|
| 65 | <d number='1' str='abc'>TEXT2</d> |
|---|
| 66 | <b number='2'><!--COMMENT--></b> |
|---|
| 67 | </c> |
|---|
| 68 | </a> |
|---|
| 69 | XML |
|---|
| 70 | doc = REXML::Document.new(source) |
|---|
| 71 | predicate = "count(child::node()|" + |
|---|
| 72 | "following-sibling::node()|" + |
|---|
| 73 | "preceding-sibling::node())=0" |
|---|
| 74 | m = REXML::XPath.match(doc, "/descendant-or-self::node()[#{predicate}]") |
|---|
| 75 | assert_equal( [REXML::Text.new("TEXT1"), |
|---|
| 76 | REXML::Text.new("TEXT2"), |
|---|
| 77 | REXML::Comment.new("COMMENT")], |
|---|
| 78 | m ) |
|---|
| 79 | end |
|---|
| 80 | end |
|---|