diff --git a/utils/xpath/xpath.go b/utils/xpath/xpath.go index f18f02fe..c7618b4e 100644 --- a/utils/xpath/xpath.go +++ b/utils/xpath/xpath.go @@ -23,16 +23,17 @@ import ( ) var ( - idPattern = `[a-zA-Z_][a-zA-Z\d\_\-\.]*` + idPattern = `[a-zA-Z_][a-zA-Z\d\_\-\.]*` + nodeIdPattern = `(?:` + idPattern + `:)?` + idPattern // YANG identifiers must follow RFC 6020: // https://tools.ietf.org/html/rfc6020#section-6.2. - idRe = regexp.MustCompile(`^(?:`+idPattern+`:)?` + idPattern + `$`) + idRe = regexp.MustCompile(`^` + nodeIdPattern + `$`) // The sting representation of List key value pairs must follow the // following pattern: [key=value], where key is the List key leaf name, // and value is the string representation of key leaf value. kvRe = regexp.MustCompile(`^\[` + // Key leaf name must be a valid YANG identifier. - idPattern + `=` + + nodeIdPattern + `=` + // Key leaf value must be a non-empty string, which may contain // newlines. Use (?s) to turn on s flag to match newlines. `((?s).+)` + diff --git a/utils/xpath/xpath_test.go b/utils/xpath/xpath_test.go index ae844278..a4bbdd47 100644 --- a/utils/xpath/xpath_test.go +++ b/utils/xpath/xpath_test.go @@ -277,6 +277,11 @@ func TestParseElement(t *testing.T) { elem: "a[k1=v1][k2=v2]", expectOK: true, want: []interface{}{"a", map[string]string{"k1": "v1", "k2": "v2"}}, + }, { + desc: "test list with xpath expression in key", + elem: "interface[name=current()]", + expectOK: true, + want: []interface{}{"interface", map[string]string{"name": "current()"}}, }} for _, test := range tests { @@ -360,6 +365,16 @@ func TestParseStringPath(t *testing.T) { }, { desc: "test path containing a multi-key List, second key-value pair without [ and ]", path: "/a/b[k1=10]k2=abc/c", + }, { + desc: "test path containing prefix", + path: "/openconfig-interfaces:interface", + expectOK: true, + want: []interface{}{"openconfig-interfaces:interface"}, + }, { + desc: "test path containing prefix in path and List", + path: "/oc-if:interfaces/oc-if:interface[oc-if:name=current()/../interface]/oc-if:subinterfaces", + expectOK: true, + want: []interface{}{"oc-if:interfaces", "oc-if:interface", map[string]string{"oc-if:name": "current()/../interface"}, "oc-if:subinterfaces"}, }} for _, test := range tests {