Blogs

Scripting How-To: New namespaces and their quirks

By Erdem posted 08-09-2015 06:04

  

Overview

Among the many changes introduced in SLAX 1.1 are four new namespaces that are required for many of the new functions and statements: slaxbitcurl, and xutil. This blog post provides some background on the namespaces themselves, without attention paid to the specific functions available in each. If you're looking for a basic overview of the new functions, then take a look at the technical docs: slaxbitcurl, and xutil. This applies to SLAX version 1.1 and higher.

Feature

 

The SLAX Namespace


The most important of these new SLAX 1.1 namespaces is the slax namespace. It is used both for new functions (many of which are renamed jcs functions) as well as instruction elements, the underlying cogs in the machinery behind much of the SLAX 1.1 features such as while loops and mvars.

 

slax:output( "string" ) performs the same action as jcs:output( "string" ).


While( $index < 10 ) is converted behind the scenes into <slax:while xmlns:slax="http://xml.libslax.org/slax" test="$index &lt; 10">.

The slax namespace is unique, however, in that you typically should never have to define it within your code because the script processor automatically adds it whenever a slax function or statement is used that requires it. In other words, the following code works just fine:

01	version 1.1;
02	 
03	ns junos = "http://xml.juniper.net/junos/*/junos";
04	ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
05	ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
06	 
07	import "../import/junos.xsl";
08	 
09	template junoscript {
10	    expr slax:output( "Look, I didn't declare it and it works anyway!" );
11	}

Output

 

1	admin@CHI-M7i-1> op url /var/run/scripts/op/test.slax
2	Look, I didn't declare it and it works anyway!

Note: As you can see, the starting template changed in SLAX 1.1 (even though "match /" still works fine). I plan to cover the new boilerplates in a future blog post.


If you're curious how this works, take a look at the resulting XSLT code:

 

1	admin@CHI-M7i-1> file show test.xslt
2	<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
3	<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:junos="http://xml.juniper.net/junos/*/junos" xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0" xmlns:slax="http://xml.libslax.org/slax" version="1.0" extension-element-prefixes="slax">
4	  <xsl:import href="../import/junos.xsl"/>
5	  <xsl:template name="junoscript">
6	    <xsl:value-of xmlns:slax="http://xml.libslax.org/slax" select="slax:output(&quot;Look, I didn't declare it and it works anyway!&quot;)"/>
7	  </xsl:template>
8	</xsl:stylesheet>

As you can see, the slax namespace was automatically added and declared as an extension namespace. This latter part is critical because without that extension declaration the new SLAX 1.1 instruction elements such as <slax:while> would be interpreted as data rather than instructions, which brings us to the first of two quirks about how Junos OS handles the slax namespace: if you declare the slax namespace in your scriptbut do not declare it as an extension prefixthen you'll kill while loops, mvars, and other SLAX 1.1 functionality.


In other words, do not do this:

 

1	/* Bad code...bad, bad, bad */
2	ns slax = "http://xml.libslax.org/slax";

The problem is that Junos OS currently only adds the slax namespace as an extension prefix if it isn't currently declared, so if you declare it then you're on your own and you better do it right.


Here is the right way:

 

1	ns slax extension = "http://xml.libslax.org/slax";

But why would you want to declare it if the script processor adds it automatically? Well, that brings us to the second quirk in the handling of the slax namespace: if you don't declare it, and you don't use it, then function-available() won't work for slax functions.

 

Here's an example of what I mean by that. We know that slax:output() is a valid
function and that it doesn't require you to declare the slax namespace, right?

 

01	version 1.1;
02	 
03	ns junos = "http://xml.juniper.net/junos/*/junos";
04	ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
05	ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
06	 
07	import "../import/junos.xsl";
08	 
09	template junoscript {
10	    <output> "Excuse me, but have you heard of slax:output()?: " _ function-available( "slax:output" );
11	}

Apparently not:

 

1	admin@CHI-M7i-1> op url /var/run/scripts/op/test.slax
2	error: runtime error: file /var/tmp/tmp_opFz1p7e/tmp-op-script.NMOSX7/test.slax line 10 element value-of
3	error: function-available() : prefix slax is not bound
4	error: stylesheet failed: /var/tmp/tmp_opFz1p7e/tmp-op-script.NMOSX7/test.slax

The problem is that the script processor thinks you don't need the namespace so it doesn't declare it and, because it doesn't declare it, function-available() doesn't know that any slax functions exist. A corner-case, sure, but if you do plan to use function-available(), then you might be better off declaring the slax namespace in your script. That said, if you do declare it, then declare it right: as an extension namespace.


Update: Although I haven't tested this scenario, I suspect the same problem exists with the element-available() function.

Extension Namespaces: bit, curl, and xutil


The other three namespacesbitcurl, and xutilcan be considered together because they share the same requirements and behavior. Each provides new script functions such as those currently available through EXSLT or other sources; however, unlike most EXSLT namespaces, these three namespaces must always be configured as extension namespaces, a departure from normal XSLT practice where a namespace is only defined as an extension namespace if there are elements using that namespace that should be processed as instruction elements rather than data. (Examples of instruction elements include <func:function> and <exsl:document>.)


So why must bit, curl, and xutil be defined as extension namespaces if they contain no instruction elements? The reason is due to a new dynamic library mechanism introduced in SLAX 1.1 where, rather than loading them all by default, extension libraries are only loaded if the script being processed declares the library's namespace as an extension namespace. This dynamic behavior creates flexibility in what extension libraries are supported by the script processor—although Junos OS doesn't permit users to add new libraries today—and should make it easier to add additional official libraries to Junos OS in the future, but the main impact that script writers see today is that bit, curl, and xutil—the first available dynamically loaded extension libraries—will only be loaded into the script processor when they are declared as extension namespaces.


Do you really need to know all that? Perhaps not
but the bottom line is that, when working with bit, curl, or xutil functions, make sure you declare the namespaces as extension namespaces:

 

1	ns xutil extension = "http://xml.libslax.org/xutil";
2	ns bit extension = "http://xml.libslax.org/bit";
3	ns curl extension = "http://xml.libslax.org/curl

Note: There is no change to any of the current namespaces used in SLAX 1.0, so there is no need to declare EXSLT namespaces as extension namespaces unless they actually contain instruction elements.

Source

 

Original from Curtis Call blog post Oct. 9, 2012. Released to TechWiki with permission.


#How-To
#Slax
#JUNOS