xpath
xpath copied to clipboard
Implement if-then-else Xpath expression
support if expressions
Coverage decreased (-0.4%) to 76.3% when pulling 69c2a883fc71bcad06c28040db25dc36c3a65d51 on davidzr:master into cd2afb821d43992abcefe1c70b1b41af5b640179 on antchfx:master.
Hello, thanks for your contribution first. I am not familiar with if-else-then
and do not fully understand where it can apply. So can your give some example.
I am writing some test code to test if-then-else
to test, Please forgive me if I'm spoke wrong.
example 1:
s := `<aa/><a id="1"><aa>1</aa></a><a id="2"><bb/></a>`
doc, err := xmlquery.Parse(strings.NewReader(s))
exp, err := xpath.Compile("if (//a[@id='2']) then 1 else 2")
if err != nil {
panic(err)
}
fmt.Println(exp.Evaluate(xmlquery.CreateXPathNavigator(doc)).(float64))
output: 1
The above code expected value is "2" but got "1".
example 2:
s := `<aa/><a id="1"><aa>1</aa></a><a id="2"><bb/></a>`
doc, err := xmlquery.Parse(strings.NewReader(s))
exp, err := xpath.Compile("if (//a[@id='1']) then //aa else //bb")
if err != nil {
panic(err)
}
//fmt.Println(exp.Evaluate(xmlquery.CreateXPathNavigator(doc)).(float64))
iter := exp.Select(xmlquery.CreateXPathNavigator(doc))
for iter.MoveNext() {
n := iter.Current().(*xmlquery.NodeNavigator)
fmt.Printf(n.Current().OutputXML(true))
}
output
<aa></aa><aa>1</aa>
In my mind, the above code should output one "aa" but got two "aa".
Hi, thanks!
I'm implementing it because xml e-invoices requested by governments do a lot of crazy validations like in [1]
I implemented it as follows:
if (test) then pass else nopass
if the test returns true, then do wathever is "then" expression, otherwise do whatever if in "else" expression. In your case if (//a[@id='2']) then 1 else 2
is the same as: if (exists(//a[@id='2'])) then 1 else 2
therefore returns "1". So in if (//a[@id='1']) then //aa else //bb
would return all //aa
nodes.
But I think you are right, I should add context to the return expression, so in case of:
if (//a[@id='1']) then . else false()
should return the <a id="1"><aa>1</aa></a>
node.
Let me work on this and I will update you once I get it done.
[1] Algorithm to verify citizen id: "if (number(string-length($nitwithout)) = 5) then (number($a) * 19) + (number($b) * 17) + (number($c) * 13) + (number($d) * 7) + (number($e) * 3) else if (number(string-length($nitwithout)) = 6) then (number($a) * 23) + (number($b) * 19) + (number($c) * 17) + (number($d) * 13) + (number($e) * 7) + (number($f) * 3) else if (number(string-length($nitwithout)) = 7) then (number($a) * 29) + (number($b) * 23) + (number($c) * 19) + (number($d) * 17) + (number($e) * 13) + (number($f) * 7) + (number($g) * 3) else if (number(string-length($nitwithout)) = 8) then (number($a) * 37) + (number($b) * 29) + (number($c) * 23) + (number($d) * 19) + (number($e) * 17) + (number($f) * 13) + (number($g) * 7) + (number($h) * 3) else if (number(string-length($nitwithout)) = 9) then ((number($a) * 41) + (number($b) * 37) + (number($c) * 29) + (number($d) * 23) + (number($e) * 19) + (number($f) * 17) + (number($g) * 13) + (number($h) * 7) + (number($i) * 3)) else if (number(string-length($nitwithout)) = 10) then ((number($a) * 43) + (number($b) * 41) + (number($c) * 37) + (number($d) * 29) + (number($e) * 23) + (number($f) * 19) + (number($g) * 17) + (number($h) * 13) + (number($i) * 7) + (number($j) * 3)) else if (number(string-length($nitwithout)) = 11) then ((number($a) * 47) + (number($b) * 43) + (number($c) * 41) + (number($d) * 37) + (number($e) * 29) + (number($f) * 23) + (number($g) * 19) + (number($h) * 17) + (number($i) * 13) + (number($j) * 7) + (number($k) * 3)) else if (number(string-length($nitwithout)) = 12) then ((number($a) * 53) + (number($b) * 47) + (number($c) * 43) + (number($d) * 41) + (number($e) * 37) + (number($f) * 29) + (number($g) * 23) + (number($h) * 19) + (number($i) * 17) + (number($j) * 13) + (number($k) * 7) + (number($l) * 3)) else if (number(string-length($nitwithout)) = 13) then ((number($a) * 59) + (number($b) * 53) + (number($c) * 47) + (number($d) * 43) + (number($e) * 41) + (number($f) * 37) + (number($g) * 29) + (number($h) * 23) + (number($i) * 19) + (number($j) * 17) + (number($k) * 13) + (number($l) * 7) + (number($m) * 3)) else if (number(string-length($nitwithout)) = 14) then ((number($a) * 67) + (number($b) * 59) + (number($c * 53) + (number($d) * 47) + (number($e) * 43) + (number($f) * 41) + (number($g) * 37) + (number($h) * 29) + (number($i) * 23) + (number($j) * 19) + (number($k) * 17) + (number($l) * 13) + (number($m) * 7) + (number($n) * 3))) else if (number(string-length($nitwithout)) = 15) then ((number($a) * 71) + (number($b) * 67) + (number($c) * 59) + (number($d * 53) + (number($e) * 47) + (number($f) * 43) + (number($g) * 41) + (number($h) * 37) + (number($i) * 29) + (number($j) * 23) + (number($k) * 19) + (number($l) * 17) + (number($m) * 13) + (number($n) * 7) + (number($o) * 3))) else ''"
I agree your point, if (//a[@id='2']) then 1 else 2
is the same as: if (exists(//a[@id='2'])) then 1 else 2
. it is my mistake, if (//a[@id='2']) then 1 else 2
should return 1 not 2.
another expression on example 2: if (//a[@id='1']) then //aa else //bb
, there are could be have two expression, one is query on current context(like ./
), another might be query all(like //
), is there any example on this case?
another expression on example 2:
if (//a[@id='1']) then //aa else //bb
, there are could be have two expression, one is query on current context(like./
), another might be query all(like//
), is there any example on this case?
Yes, one common example is to concat the returned node value:
if (//a[@id='1']) then concat(./,'-','another expression') else ''
Are there any plans to revive this PR? If @davidzr lost interest in it, perhaps I take take a look at taking it over eventually (when I approach the need in my work)
Hello @yrashk, I would be grateful if you can take a look at it, I don't fully understand how context works in the if-else statement.