From c648531f5eaceeff376fc2b8ef874d3e118cad0a Mon Sep 17 00:00:00 2001 From: Rainer Fernbach Date: Wed, 10 Aug 2016 20:56:24 +0200 Subject: [PATCH 1/3] Added simple position() predicate --- path.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/path.go b/path.go index db38ed5..3a6dc06 100644 --- a/path.go +++ b/path.go @@ -134,9 +134,33 @@ func (s *pathStepState) next() bool { func (s *pathStepState) test(pred predicate) bool { switch pred := pred.(type) { case positionPredicate: - if pred.pos == s.pos { - return true + switch pred.op { + case EQ: + if pred.pos == s.pos { + return true + } + case NEQ: + if pred.pos != s.pos { + return true + } + case LT: + if pred.pos > s.pos { + return true + } + case LTEQ: + if pred.pos >= s.pos { + return true + } + case GT: + if pred.pos < s.pos { + return true + } + case GTEQ: + if pred.pos <= s.pos { + return true + } } + case existsPredicate: if pred.path.Exists(s.node) { return true @@ -363,8 +387,20 @@ func (s *pathStepState) _next() bool { return false } +type Operator int + +const ( + EQ Operator = iota + NEQ + LT + GT + LTEQ + GTEQ +) + type positionPredicate struct { pos int + op Operator } type existsPredicate struct { @@ -580,7 +616,17 @@ func (c *pathCompiler) parsePath() (path *Path, err error) { if pos == 0 { return nil, c.errorf("positions start at 1") } - next = positionPredicate{pos} + next = positionPredicate{pos, EQ} + } else if c.skipString("position()") { + c.skipSpaces() + op, ok := c.parseOp() + c.skipSpaces() + pos, ok2 := c.parseInt() + + if (!ok || !ok2) { + return nil, c.errorf("invalid position() predicate") + } + next = positionPredicate{pos, op} } else if c.skipString("contains(") { path, err := c.parsePath() if err != nil { @@ -729,6 +775,25 @@ func (c *pathCompiler) parseInt() (v int, ok bool) { return v, true } +func (c *pathCompiler) parseOp() (op Operator, ok bool) { + if c.skipByte('=') { + return EQ, true + } else if c.skipByte('!') && c.skipByte('=') { + return NEQ, true + } else if c.skipByte('<') { + if c.skipByte('=') { + return LTEQ, true + } + return LT, true + } else if c.skipByte('>') { + if c.skipByte('=') { + return GTEQ, true + } + return GT, true + } + return -1, false +} + func (c *pathCompiler) skipByte(b byte) bool { if c.i < len(c.path) && c.path[c.i] == b { c.i++ From db68aec23e6816b1c9ca88f0f06fb785103846d0 Mon Sep 17 00:00:00 2001 From: Adam Bouqdib Date: Wed, 25 Jan 2017 07:40:02 +0100 Subject: [PATCH 2/3] Add last() function --- path.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/path.go b/path.go index db38ed5..f73b1bf 100644 --- a/path.go +++ b/path.go @@ -137,6 +137,11 @@ func (s *pathStepState) test(pred predicate) bool { if pred.pos == s.pos { return true } + case lastPredicate: + ps := *s + if !ps._next() { + return true + } case existsPredicate: if pred.path.Exists(s.node) { return true @@ -367,6 +372,8 @@ type positionPredicate struct { pos int } +type lastPredicate struct{} + type existsPredicate struct { path *Path } @@ -399,6 +406,7 @@ type predicate interface { } func (positionPredicate) predicate() {} +func (lastPredicate) predicate() {} func (existsPredicate) predicate() {} func (equalsPredicate) predicate() {} func (containsPredicate) predicate() {} @@ -581,6 +589,8 @@ func (c *pathCompiler) parsePath() (path *Path, err error) { return nil, c.errorf("positions start at 1") } next = positionPredicate{pos} + } else if c.skipString("last()") { + next = lastPredicate{} } else if c.skipString("contains(") { path, err := c.parsePath() if err != nil { From ed05bb093f3522f2d050cb1df5f85398f137c2dd Mon Sep 17 00:00:00 2001 From: Adam Bouqdib Date: Thu, 30 Apr 2020 17:21:34 +0100 Subject: [PATCH 3/3] Update module path in tests --- all_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/all_test.go b/all_test.go index dd8ae18..6457a97 100644 --- a/all_test.go +++ b/all_test.go @@ -6,7 +6,7 @@ import ( "testing" . "gopkg.in/check.v1" - "gopkg.in/xmlpath.v2" + "gopkg.in/abemedia/xmlpath.v2" "strings" )