-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
675 additions
and
1,037 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package xpath | ||
|
||
import "testing" | ||
|
||
func Test_self(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//name/self::*`, 4, 9, 14) | ||
} | ||
|
||
func Test_child(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `/empinfo/child::*`, 3, 8, 13) | ||
test_xpath_elements(t, employee_example, `/empinfo/child::node()`, 3, 8, 13) | ||
test_xpath_values(t, employee_example, `//name/child::text()`, "Opal Kole", "Max Miller", "Beccaa Moss") | ||
test_xpath_elements(t, employee_example, `//child::employee/child::email`, 6, 11, 16) | ||
} | ||
|
||
func Test_descendant(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//employee/descendant::*`, 4, 5, 6, 9, 10, 11, 14, 15, 16) | ||
test_xpath_count(t, employee_example, `//descendant::employee`, 3) | ||
} | ||
|
||
func Test_descendant_or_self(t *testing.T) { | ||
test_xpath_tags(t, employee_example.FirstChild, `self::*`, "empinfo") | ||
test_xpath_elements(t, employee_example, `//employee/descendant-or-self::*`, 3, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16) | ||
test_xpath_count(t, employee_example, `//descendant-or-self::employee`, 3) | ||
} | ||
|
||
func Test_ancestor(t *testing.T) { | ||
test_xpath_tags(t, employee_example, `//employee/ancestor::*`, "empinfo") // | ||
test_xpath_elements(t, employee_example, `//ancestor::name`, 4, 9, 14) | ||
} | ||
|
||
func Test_ancestor_or_self(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//employee/ancestor-or-self::*`, 2, 3, 8, 13) | ||
test_xpath_elements(t, employee_example, `//name/ancestor-or-self::employee`, 2, 3, 8, 13) | ||
} | ||
|
||
func Test_parent(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//name/parent::*`, 3, 8, 13) | ||
test_xpath_elements(t, employee_example, `//name/parent::employee`, 3, 8, 13) | ||
} | ||
|
||
func Test_attribute(t *testing.T) { | ||
test_xpath_values(t, employee_example, `//attribute::id`, "1", "2", "3") | ||
test_xpath_tags(t, employee_example, `//attribute::*`, "id", "discipline", "experience", "id", "from", "discipline", "experience", "id", "discipline") | ||
} | ||
|
||
func Test_following(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//employee[@id=1]/following::*`, 8, 9, 10, 11, 13, 14, 15, 16) | ||
} | ||
|
||
func Test_following_sibling(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//employee[@id=1]/following-sibling::*`, 8, 13) | ||
test_xpath_elements(t, employee_example, `//employee[@id=1]/following-sibling::employee`, 8, 13) | ||
} | ||
|
||
func Test_preceding(t *testing.T) { | ||
//testXPath3(t, html, "//li[last()]/preceding-sibling::*[2]", selectNode(html, "//li[position()=2]")) | ||
//testXPath3(t, html, "//li/preceding::*[1]", selectNode(html, "//h1")) | ||
test_xpath_elements(t, employee_example, `//employee[@id=3]/preceding::*`, 8, 9, 10, 11, 3, 4, 5, 6) | ||
} | ||
|
||
func Test_preceding_sibling(t *testing.T) { | ||
test_xpath_elements(t, employee_example, `//employee[@id=3]/preceding-sibling::*`, 8, 3) | ||
} | ||
|
||
func Test_namespace(t *testing.T) { | ||
// TODO | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package xpath | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
// `*/employee` [Not supported] | ||
|
||
func TestRelativePaths(t *testing.T) { | ||
test_xpath_elements(t, book_example, `//book`, 3, 9, 15, 25) | ||
test_xpath_elements(t, book_example, `//bookstore/book`, 3, 9, 15, 25) | ||
test_xpath_tags(t, book_example, `//book/..`, "bookstore") | ||
test_xpath_elements(t, book_example, `//book[@category="cooking"]/..`, 2) | ||
test_xpath_elements(t, book_example, `//book/year[text() = 2005]/../..`, 2) // bookstore | ||
test_xpath_elements(t, book_example, `//book/year/../following-sibling::*`, 9, 15, 25) | ||
test_xpath_count(t, book_example, `//bookstore/book/*`, 20) | ||
test_xpath_tags(t, html_example, "//title/../..", "html") | ||
test_xpath_elements(t, html_example, "//ul/../p", 19) | ||
} | ||
|
||
func TestAbsolutePaths(t *testing.T) { | ||
test_xpath_elements(t, book_example, `bookstore`, 2) | ||
test_xpath_elements(t, book_example, `bookstore/book`, 3, 9, 15, 25) | ||
test_xpath_elements(t, book_example, `(bookstore/book)`, 3, 9, 15, 25) | ||
test_xpath_elements(t, book_example, `bookstore/book[2]`, 9) | ||
test_xpath_elements(t, book_example, `bookstore/book[last()]`, 25) | ||
test_xpath_elements(t, book_example, `bookstore/book[last()]/title`, 26) | ||
test_xpath_values(t, book_example, `/bookstore/book[last()]/title/text()`, "Learning XML") | ||
test_xpath_values(t, book_example, `/bookstore/book[@category = "children"]/year`, "2005") | ||
test_xpath_elements(t, book_example, `bookstore/book/..`, 2) | ||
test_xpath_elements(t, book_example, `/bookstore/*`, 3, 9, 15, 25) | ||
test_xpath_elements(t, book_example, `/bookstore/*/title`, 4, 10, 16, 26) | ||
} | ||
|
||
func TestAttributes(t *testing.T) { | ||
test_xpath_tags(t, html_example.FirstChild, "@*", "lang") | ||
test_xpath_tags(t, employee_example, `//@*`, "id", "discipline", "experience", "id", "from", "discipline", "experience", "id", "discipline") | ||
test_xpath_values(t, employee_example, `//@discipline`, "web", "DBA", "appdev") | ||
test_xpath_count(t, employee_example, `//employee/@id`, 3) | ||
} | ||
|
||
func TestExpressions(t *testing.T) { | ||
test_xpath_elements(t, book_example, `//book[@category = "cooking"] | //book[@category = "children"]`, 3, 9) | ||
test_xpath_count(t, html_example, `//ul/*`, 3) | ||
test_xpath_count(t, html_example, `//ul/*/a`, 3) | ||
// Sequence | ||
// | ||
// table/tbody/tr/td/(para, .[not(para)], ..) | ||
} | ||
|
||
func TestSequence(t *testing.T) { | ||
// `//table/tbody/tr/td/(para, .[not(para)],..)` | ||
test_xpath_count(t, html_example, `//body/(h1, h2, p)`, 2) | ||
test_xpath_count(t, html_example, `//body/(h1, h2, p, ..)`, 3) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
package xpath | ||
|
||
import ( | ||
"math" | ||
"testing" | ||
) | ||
|
||
// Some test examples from http://zvon.org/comp/r/ref-XPath_2.html | ||
|
||
func Test_func_boolean(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `true()`, true) | ||
test_xpath_eval(t, empty_example, `false()`, false) | ||
test_xpath_eval(t, empty_example, `boolean(0)`, false) | ||
test_xpath_eval(t, empty_example, `boolean(1)`, true) | ||
test_xpath_eval(t, empty_example, `boolean(2)`, true) | ||
test_xpath_eval(t, empty_example, `boolean(true)`, false) | ||
test_xpath_eval(t, empty_example, `boolean(1 > 2)`, false) | ||
test_xpath_eval(t, book_example, `boolean(//*[@lang])`, true) | ||
test_xpath_eval(t, book_example, `boolean(//*[@x])`, false) | ||
} | ||
|
||
func Test_func_name(t *testing.T) { | ||
test_xpath_eval(t, html_example, `name(//html/@lang)`, "lang") | ||
test_xpath_eval(t, html_example, `name(html/head/title)`, "title") | ||
test_xpath_count(t, html_example, `//*[name() = "li"]`, 3) | ||
} | ||
|
||
func Test_func_not(t *testing.T) { | ||
//test_xpath_eval(t, empty_example, `not(0)`, true) | ||
//test_xpath_eval(t, empty_example, `not(1)`, false) | ||
test_xpath_elements(t, employee_example, `//employee[not(@id = "1")]`, 8, 13) | ||
test_xpath_elements(t, book_example, `//book[not(year = 2005)]`, 15, 25) | ||
test_xpath_count(t, book_example, `//book[not(title)]`, 0) | ||
} | ||
|
||
func Test_func_ceiling_floor(t *testing.T) { | ||
test_xpath_eval(t, empty_example, "ceiling(5.2)", float64(6)) | ||
test_xpath_eval(t, empty_example, "floor(5.2)", float64(5)) | ||
} | ||
|
||
func Test_func_concat(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `concat("1", "2", "3")`, "123") | ||
//test_xpath_eval(t, empty_example, `concat("Ciao!", ())`, "Ciao!") | ||
test_xpath_eval(t, book_example, `concat(//book[1]/title, ", ", //book[1]/year)`, "Everyday Italian, 2005") | ||
} | ||
|
||
func Test_func_contains(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `contains("tattoo", "t")`, true) | ||
test_xpath_eval(t, empty_example, `contains("tattoo", "T")`, false) | ||
test_xpath_eval(t, empty_example, `contains("tattoo", "ttt")`, false) | ||
//test_xpath_eval(t, empty_example, `contains("", ())`, true) | ||
test_xpath_elements(t, book_example, `//book[contains(title, "Potter")]`, 9) | ||
test_xpath_elements(t, book_example, `//book[contains(year, "2005")]`, 3, 9) | ||
assertPanic(t, func() { selectNode(html_example, "//*[contains(0, 0)]") }) | ||
} | ||
|
||
func Test_func_count(t *testing.T) { | ||
test_xpath_eval(t, book_example, `count(//book)`, float64(4)) | ||
test_xpath_eval(t, book_example, `count(//book[3]/author)`, float64(5)) | ||
} | ||
|
||
func Test_func_ends_with(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `ends-with("tattoo", "tattoo")`, true) | ||
test_xpath_eval(t, empty_example, `ends-with("tattoo", "atto")`, false) | ||
test_xpath_elements(t, book_example, `//book[ends-with(@category,'ing')]`, 3) | ||
test_xpath_elements(t, book_example, `//book[ends-with(./price,'.99')]`, 9, 15) | ||
assertPanic(t, func() { selectNode(html_example, `//*[ends-with(0, 0)]`) }) // arg must be start with string | ||
assertPanic(t, func() { selectNode(html_example, `//*[ends-with(name(), 0)]`) }) | ||
} | ||
|
||
func Test_func_last(t *testing.T) { | ||
test_xpath_elements(t, book_example, `//bookstore[last()]`, 2) | ||
test_xpath_elements(t, book_example, `//bookstore/book[last()]`, 25) | ||
test_xpath_elements(t, html_example, `//ul/li[last()]`, 15) | ||
test_xpath_elements(t, html_example, `(//ul/li)[last()]`, 15) | ||
} | ||
|
||
func Test_func_local_name(t *testing.T) { | ||
// TODO | ||
} | ||
|
||
func Test_func_starts_with(t *testing.T) { | ||
test_xpath_eval(t, employee_example, `starts-with("tattoo", "tat")`, true) | ||
test_xpath_eval(t, employee_example, `starts-with("tattoo", "att")`, false) | ||
test_xpath_elements(t, book_example, `//book[starts-with(title,'Everyday')]`, 3) | ||
assertPanic(t, func() { selectNode(html_example, `//*[starts-with(0, 0)]`) }) | ||
assertPanic(t, func() { selectNode(html_example, `//*[starts-with(name(), 0)]`) }) | ||
} | ||
|
||
func Test_func_string(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `string(1.23)`, "1.23") | ||
test_xpath_eval(t, empty_example, `string(3)`, "3") | ||
} | ||
|
||
func Test_func_string_join(t *testing.T) { | ||
//test_xpath_eval(t, empty_example, `string-join(('Now', 'is', 'the', 'time', '...'), '')`, "Now is the time ...") | ||
test_xpath_eval(t, empty_example, `string-join("some text", ";")`, "some text") | ||
test_xpath_eval(t, book_example, `string-join(//book/@category, ";")`, "cooking;children;web;web") | ||
} | ||
|
||
func Test_func_string_length(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `string-length("Harp not on that string, madam; that is past.")`, float64(45)) | ||
test_xpath_eval(t, empty_example, `string-length(normalize-space(' abc '))`, float64(3)) | ||
test_xpath_eval(t, html_example, `string-length(//title/text())`, float64(len("My page"))) | ||
test_xpath_eval(t, html_example, `string-length(//html/@lang)`, float64(len("en"))) | ||
test_xpath_count(t, employee_example, `//employee[string-length(@id) > 0]`, 3) // = //employee[@id] | ||
} | ||
|
||
func Test_func_substring(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `substring("motor car", 6)`, " car") | ||
test_xpath_eval(t, empty_example, `substring("metadata", 4, 3)`, "ada") | ||
//test_xpath_eval(t, empty_example, `substring("12345", 5, -3)`, "") ?? it should be 1 ?? | ||
//test_xpath_eval(t, empty_example, `substring("12345", 1.5, 2.6)`, "234") | ||
//test_xpath_eval(t, empty_example, `substring("12345", 0, 3)`, "12") // panic?? | ||
//test_xpath_eval(t, empty_example, `substring("12345", 5, -3)`, "1") | ||
test_xpath_eval(t, html_example, `substring(//title/child::node(), 1)`, "My page") | ||
} | ||
|
||
func Test_func_substring_after(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `substring-after("tattoo", "tat")`, "too") | ||
test_xpath_eval(t, empty_example, `substring-after("tattoo", "tattoo")`, "") | ||
} | ||
|
||
func Test_func_substring_before(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `substring-before("tattoo", "attoo")`, "t") | ||
test_xpath_eval(t, empty_example, `substring-before("tattoo", "tatto")`, "") | ||
} | ||
|
||
func Test_func_sum(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `sum(1 + 2)`, float64(3)) | ||
test_xpath_eval(t, empty_example, `sum(1.1 + 2)`, float64(3.1)) | ||
test_xpath_eval(t, book_example, `sum(//book/price)`, float64(149.93)) | ||
assertPanic(t, func() { selectNode(html_example, `//title[sum('Hello') = 0]`) }) | ||
} | ||
|
||
func Test_func_translate(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `translate("bar","abc","ABC")`, "BAr") | ||
test_xpath_eval(t, empty_example, `translate("--aaa--","abc-","ABC")`, "AAA") | ||
test_xpath_eval(t, empty_example, `translate("abcdabc", "abc", "AB")`, "ABdAB") | ||
test_xpath_eval(t, empty_example, `translate('The quick brown fox', 'brown', 'red')`, "The quick red fdx") | ||
} | ||
|
||
func Test_func_matches(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `matches("abracadabra", "bra")`, true) | ||
test_xpath_eval(t, empty_example, `matches("abracadabra", "(?i)^A.*A$")`, true) | ||
test_xpath_eval(t, empty_example, `matches("abracadabra", "^a.*a$")`, true) | ||
test_xpath_eval(t, empty_example, `matches("abracadabra", "^bra")`, false) | ||
assertPanic(t, func() { selectNode(html_example, `//*[matches()]`) }) // arg len check failure | ||
assertPanic(t, func() { selectNode(html_example, "//*[matches(substring(), 0)]") }) // first arg processing failure | ||
assertPanic(t, func() { selectNode(html_example, "//*[matches(@href, substring())]") }) // second arg processing failure | ||
assertPanic(t, func() { selectNode(html_example, "//*[matches(@href, 0)]") }) // second arg not string | ||
assertPanic(t, func() { selectNode(html_example, "//*[matches(@href, '[invalid')]") }) // second arg invalid regexp | ||
// testing unexpected the regular expression. | ||
_, err := Compile(`//*[matches(., '^[\u0621-\u064AA-Za-z\-]+')]`) | ||
assertErr(t, err) | ||
_, err = Compile(`//*[matches(., '//*[matches(., '\w+`) | ||
assertErr(t, err) | ||
} | ||
|
||
func Test_func_number(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `number(10)`, float64(10)) | ||
test_xpath_eval(t, empty_example, `number(1.11)`, float64(1.11)) | ||
test_xpath_eval(t, empty_example, `number("10") > 10`, false) | ||
test_xpath_eval(t, empty_example, `number("10") = 10`, true) | ||
test_xpath_eval(t, empty_example, `number("123") < 1000`, true) | ||
assertTrue(t, math.IsNaN(MustCompile(`number("123a")`).Evaluate(createNavigator(empty_example)).(float64))) | ||
} | ||
|
||
func Test_func_position(t *testing.T) { | ||
test_xpath_elements(t, book_example, `//book[position() = 1]`, 3) | ||
//test_xpath_elements(t, book_example, `//book[(position() mod 2) = 0]`, 9, 25) | ||
//test_xpath_elements(t, book_example, `//book[position() = last()]`, 25) | ||
//test_xpath_elements(t, book_example, `//book/*[position() = 1]`, 4, 10, 16, 26) | ||
test_xpath_elements(t, book_example, `(//book/title)[position() = 1]`, 3) | ||
} | ||
|
||
func Test_func_replace(t *testing.T) { | ||
test_xpath_eval(t, empty_example, `replace('aa-bb-cc','bb','ee')`, "aa-ee-cc") | ||
test_xpath_eval(t, empty_example, `replace("abracadabra", "bra", "*")`, "a*cada*") | ||
test_xpath_eval(t, empty_example, `replace("abracadabra", "a", "")`, "brcdbr") | ||
// The below xpath expressions is not supported yet | ||
// | ||
//test_xpath_eval(t, empty_example, `replace("abracadabra", "a.*a", "*")`, "*") | ||
//test_xpath_eval(t, empty_example, `replace("abracadabra", "a.*?a", "*")`, "*c*bra") | ||
//test_xpath_eval(t, empty_example, `replace("abracadabra", ".*?", "$1")`, "*c*bra") // error, because the pattern matches the zero-length string | ||
//test_xpath_eval(t, empty_example, `replace("AAAA", "A+", "b")`, "b") | ||
//test_xpath_eval(t, empty_example, `replace("AAAA", "A+?", "b")`, "bbb") | ||
//test_xpath_eval(t, empty_example, `replace("darted", "^(.*?)d(.*)$", "$1c$2")`, "carted") | ||
//test_xpath_eval(t, empty_example, `replace("abracadabra", "a(.)", "a$1$1")`, "abbraccaddabbra") | ||
} | ||
|
||
func Test_func_reverse(t *testing.T) { | ||
//test_xpath_eval(t, employee_example, `reverse(("hello"))`, "hello") // Not passed | ||
test_xpath_elements(t, employee_example, `reverse(//employee)`, 13, 8, 3) | ||
test_xpath_elements(t, employee_example, `//employee[reverse(.) = reverse(.)]`, 3, 8, 13) | ||
assertPanic(t, func() { selectNode(html_example, "reverse(concat())") }) // invalid node-sets argument. | ||
assertPanic(t, func() { selectNode(html_example, "reverse()") }) // missing node-sets argument. | ||
} | ||
|
||
func Test_func_round(t *testing.T) { | ||
test_xpath_eval(t, employee_example, `round(2.5)`, 3) // int | ||
test_xpath_eval(t, employee_example, `round(2.5)`, 3) | ||
test_xpath_eval(t, employee_example, `round(2.4999)`, 2) | ||
} | ||
|
||
func Test_func_namespace_uri(t *testing.T) { | ||
// TODO | ||
} | ||
|
||
func Test_func_normalize_space(t *testing.T) { | ||
// TODO | ||
} |
Oops, something went wrong.