Scripting How-To: Use the sequence, not, and mvar append SLAX operators

By Elevate posted 08-09-2015 05:14


Use the Sequence, Not, and mvar Append Operators

For SLAX version 1.1 and higher, you can use four new operators:

Of the four new operators, the latter three will be covered in this article.


Sequence Operator


The sequence operator, used within both for and for-each loops, is represented by three periods ... (dots). As its name implies, this operator is used to create a sequence (represented by a node-set) that a loop can then iterate through:




01	template junoscript {
02	    <output> "for-each loop:";
03	    for-each( 1 ... 5 ) {
04	        <output> .;
05	    }
06	    <output> "_\r \nfor loop:";
07	    for $i ( 3 ... 1 ) {
08	        <output> $i;
09	    }
10	}




01	for-each loop:
02	1
03	2
04	3
05	4
06	5
08	for loop:
09	3
10	2
11	1


Two things should be apparent from the above code example:


  • first, either an ascending or descending sequence can be created depending on whether the first argument is larger or smaller than the second argument;
  • second, in either case the step is always +/- 1.

In addition, the operator only handles integers (decimals are truncated), and while its argument values will often be hard coded into the script, they can be provided through variables as well.

The sequence operator works behind the scenes by creating a node-set consisting of <item> nodes, one per step from the beginning value to the ending value, each element node assigned to its appropriate step value as this example indicates:



1	template junoscript {
2	    for-each( 1 ... 3 ) {
3	        <output> name( . ) _ " = " _ .;
4	    }
5	}




1	item = 1
2	item = 2
3	item = 3


Keep in mind when using this operator, however, that because SLAX creates a node-set to represent each generated sequence, there is a memory and processing cost involved.


For example, while testing this operator on a MX80 router I observed the following processing times:

  • ~11ms for a 1000 item sequence
  • ~1.4s for a 10,000 item sequence
  • ~3.6s for a 15,000 item sequence
  • ~10s for a 20,000 item sequence
  • ~25s for a 30,000 item sequence

Very large values, like 100,000, simply hung without returning. The time reported in this paragraph is the time delta from the statement before the loop to the first iteration of the loop. It does not include the actual loop processing itself, which would obviously increase as the sequence size increased.


Not Operator


The lack of a simple 'not' operator in SLAX 1.0 has been a common observation of coders as they learn the scripting language. But this language gap has been removed in SLAX 1.1, which introduces 'not' using the standard ! symbol:




1	template junoscript {
2	    if( ! $input ) {
3	        <output> "You entered nothing";
4	    }
5	}


A lengthy explanation for this operator isn't necessary as the ! symbol is simply translated into the not() function during the SLAX to XSLT conversion process, making the behavior and details of the 'not' operator the same as the current not() function:

Converted Code Example


1	<xsl:template name="junoscript">
2	    <xsl:if test="not($input)">
3	      <output>You entered nothing</output>
4	    </xsl:if>
5	  </xsl:template>


mvar Append Operator


One of the most significant additions to SLAX 1.1 is the introduction of mutable variables. With SLAX 1.0, variable values cannot be changed once initialized, a frequent headache for script writers; however, in SLAX 1.1, variables that are defined using the mvar statement can be modified through either the set or append statements, with the set statement replacing the existing value, and the append statement adding to the existing value:



1	template junoscript {
2	    mvar $variable = "xyz";
3	    set $variable = "abc";
4	    append $variable += "def";
5	    <output> $variable;
6	}




1	abcdef


The += mvar append operator is used only in conjunction with the append statement. While it resembles the plus-equals operator from other programming languages, this SLAX operator only appends string or node values onto mvars; it does not add two numeric values together. The following example demonstrates what happens when you append one number to another:



1	template junoscript {
2	    mvar $variable = 10;
3	    append $variable += 5;
4	    <output> $variable;
5	}




1	105


As shown, the values are treated as strings rather than numbers when append is used. In fact, string concatenation is always performed when two scalar—string, number, or Booleanvalues are appended together. However, a different behavior is followed when a node-set (result tree fragments are considered node-sets by mvars) is involved. The table below summarizes the action taken by the mvar append operation based on whether the original or appended value is a node-set or a scalar:

  Original value is a node-set Original value is a scalar
Appended value is a node-set Nodes are appended into the existing XML document. Original value is replaced by the node-set. This is the same behavior as if the set statement had been used instead.
Appended value is a scalar Scalar value is appended into an existing XML document as the content of a new element named <text>. Values are combined using string concatenation.

This is demonstrated by the following code example:



01	template junoscript {
02	    mvar $interfaces = {
03	        <interface> {
04	            <name> "ge-0/0/0";
05	        }
06	    }
07	    append $interfaces += {
08	        <interface> {
09	            <name> "ge-0/0/1";
10	        }
11	    }
12	    append $interfaces += "disable";
14	    expr slax:output( xutil:xml-to-string( $interfaces ) );
15	}




1	<interface>
2	  <name>ge-0/0/0</name>
3	</interface>
4	<interface>
5	  <name>ge-0/0/1</name>
6	</interface>
7	<text>disable</text>