cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1973
Views
4
Helpful
3
Replies

xpath position()

robert.lee2
Level 1
Level 1

list temponly {

    key devname;

    uses ncs:service-data;

    ncs:servicepoint "temponly";

    leaf devname {

      type leafref {

        path "/ncs:devices/ncs:device/ncs:name";

      }

    }

    leaf-list metrics{

      type uint16;

    }

  }//list

Above is yang snippet.  And Below is my template xml

<config-template xmlns="http://tail-f.com/ns/config/1.0"

                 servicepoint="temponly">

  <devices xmlns="http://tail-f.com/ns/ncs">

    <device>

      <name>{/devname}</name>

       <config>

         <route-map xmlns="urn:ios" foreach="{/metrics}">

            <name>test3</name>

            <sequence>{position()}</sequence>

            <set>

               <metric>{.}</metric>

            </set>

         </route-map>

       </config>

    </device>

  </devices>

</config-template>

Now here is the question / issue -

When I pass the following input -

admin@ncs(config)# temponly cisco1 metrics [ 22 33 44 ]

the position function - position() - always returns 1 -

9-Feb-2018::17:49:05.691 xpath_eval() evaluating: /metrics

/temponly[devname='cisco1']/metrics[.='22']: 22

/temponly[devname='cisco1']/metrics[.='33']: 33

/temponly[devname='cisco1']/metrics[.='44']: 44

9-Feb-2018::17:49:05.692 xpath_eval() resulted in 3 nodes

9-Feb-2018::17:49:05.693 eval_expr() evaluating: string(position())

9-Feb-2018::17:49:05.693 eval_expr() result: 1

9-Feb-2018::17:49:05.694 xpath_eval() evaluating: .

/temponly[devname='cisco1']/metrics[.='22']: 22

9-Feb-2018::17:49:05.695 xpath_eval() resulted in one node

9-Feb-2018::17:49:05.695 eval_expr() evaluating: string(position())

9-Feb-2018::17:49:05.696 eval_expr() result: 1

9-Feb-2018::17:49:05.696 xpath_eval() evaluating: .

/temponly[devname='cisco1']/metrics[.='33']: 33

9-Feb-2018::17:49:05.696 xpath_eval() resulted in one node

9-Feb-2018::17:49:05.698 eval_expr() evaluating: string(position())

9-Feb-2018::17:49:05.698 eval_expr() result: 1

9-Feb-2018::17:49:05.698 xpath_eval() evaluating: .

/temponly[devname='cisco1']/metrics[.='44']: 44

9-Feb-2018::17:49:05.699 xpath_eval() resulted in one node

I guess it makes sense, since the foreach is only passing one node each time......  But what I want is the relative position, so that I can do something like -

  <sequence>{position()*10}</sequence>

- thereby auto-numbering the sequence #.  Is there a way to achieve this ?

PS - I want to do this using a template only based service - no python/java in the middle.....

Thanks

1 Accepted Solution

Accepted Solutions

dknertse
Cisco Employee
Cisco Employee

I don't think position() function can be used in this way to get the index of an element in a leaf-list. The problem is that the position() function indicates a position of the node in the currently selected node-set, and *not* a position in a list or leaf-list. So it can be useful in a predicate to select a node with a specific position (e.g. ./metrics[position()=2] which will first select the node-set of all metrics nodes (./metrics) and then selecting the second node of this node-set ([position()=2]). But in a foreach loop in template the context is changed to a single node on each iteration, so both the position() and the size (last()) for this context are 1.

The solution suggested in the previous comment will be possible in NSO 4.6 which allows to introduce a new variable in a template and increment its value using the <?set?> processing instruction. Unfortunately, I don't see a solution for you in an earlier NSO version without resorting to Java/Python.

View solution in original post

3 Replies 3

Iman1
Level 1
Level 1

Any XML expert to know the answer to above?

As an alternative solution, can a temporary variable be created inside the XML template and its value increased during each iteration of foreach loop? (to mimic the array index)

Thanks

dknertse
Cisco Employee
Cisco Employee

I don't think position() function can be used in this way to get the index of an element in a leaf-list. The problem is that the position() function indicates a position of the node in the currently selected node-set, and *not* a position in a list or leaf-list. So it can be useful in a predicate to select a node with a specific position (e.g. ./metrics[position()=2] which will first select the node-set of all metrics nodes (./metrics) and then selecting the second node of this node-set ([position()=2]). But in a foreach loop in template the context is changed to a single node on each iteration, so both the position() and the size (last()) for this context are 1.

The solution suggested in the previous comment will be possible in NSO 4.6 which allows to introduce a new variable in a template and increment its value using the <?set?> processing instruction. Unfortunately, I don't see a solution for you in an earlier NSO version without resorting to Java/Python.

gschudel
Cisco Employee
Cisco Employee

thank you Denys - appreciate the reply.

-gregg