[j-nsp] understaning the copy-node in SLAX

Martin T m4rtntns at gmail.com
Mon Feb 5 07:46:42 EST 2018


On Fri, Feb 2, 2018 at 10:05 PM, Phil Shafer <phil at juniper.net> wrote:
> Martin T writes:
>>When I run this with traceoptions enabled, then I can see that "<abc
>>a="12" b="34" c="56"/>" is present in the output document. I guess
>>that this inner for-each loop, based on my example, expands to this:
>>
>>copy-node {
>>    attribute "a" {
>>        expr 12;
>>    }
>>    attribute "b" {
>>        expr 34;
>>    }
>>    attribute "c" {
>>        expr 56;
>>    }
>>}
>>
>>Now "copy-node" does its shallow copy and copies "abc" element node
>>and specified three attribute nodes to result tree. Am I correct?
>
> copy-node create a node with the target (default .) name which you
> can then populate with contents:
>
> https://www.w3.org/TR/1999/REC-xslt-19991116#copying
>
>     The xsl:copy element provides an easy way of copying the current
>     node. Instantiating the xsl:copy element creates a copy of the
>     current node. The namespace nodes of the current node are
>     automatically copied as well, but the attributes and children
>     of the node are not automatically copied. The content of the
>     xsl:copy element is a template for the attributes and children
>     of the created node; the content is instantiated only for nodes
>     of types that can have attributes or children (i.e. root nodes
>     and element nodes).
>
> It's rather like:
>
>     element name() {
>         ...
>     }
>
>>In
>>addition, why does copy-node run only once despite the fact that it is
>>in the for-each loop? Is it because copy-node discards all the child
>>elements of its current node and thus there are no more element
>>nodes(<klm>, <name>, <name> based on my example) to loop through?
>
> It's simpler than that; it's copying the current node, so there's
> only one of them.  The nested "for-each" hits all the current node's
> attributes, so you end up with:
>
> % cat /tmp/foo.slax
> version 1.2;
>
> var $results := {
>     <abc a="12" b="34" c="56"> {
>         <klm k="78"> {
>             <name n="9"> "foo";
>         }
>     }
> }
>
> main <top> {
>     for-each ($results/abc) {
>         copy-node {
>             for-each (@*) {
>                 attribute name(.) {
>                     expr .;
>                 }
>             }
>         }
>     }
> }
> % slaxproc -E -g /tmp/foo.slax
> <?xml version="1.0"?>
> <top>
>   <abc a="12" b="34" c="56"/>
> </top>
> Bock %
>
> Thanks,
>  Phil


Thanks! And this technique is useful in case cli process expects an
element node(for example "interface-information") to have additional
attribute nodes(for example "junos:style="terse"")? Does it provide
any advantages over statically specifying the attribute node? For
example, here I rewrote two named templates and a match template of an
op script example from "Automating Junos Administration" book:

template handle-logical-intf($family) {
        <logical-interface> {
                for-each (*[name() != "address-family"]) {
                        copy-of .;
                }
                for-each (address-family[address-family-name=$family]) {
                        copy-of .;
                }
        }
}

template handle-physical-intf($family) {
        <physical-interface> {
                for-each (*[name() != "logical-interface"]) {
                        copy-of .;
                }
                for-each (logical-interface[address-family[
                                        address-family-name=$family]]) {
                        call handle-logical-intf($family=$family);
                }
        }
}

match / {
        <op-script-results> {
                var $con = jcs:open();
                var $rpc-query = {
                        <get-interface-information> {
                                <terse>;
                        }
                }
                var $results = jcs:execute($con, $rpc-query);
                expr jcs:close($con);

                if ($family) {
                        <interface-information junos:style="terse"> {
                                for-each
($results/physical-interface[logical-interface/

address-family[address-family-name=$family]]) {
                                        call
handle-physical-intf($family=$family);
                                }
                        }
                }
                else {
                        copy-of $results;
                }
        }
}

It behaves exactly the same as the one using the copy-node statements.


thanks,
Martin


More information about the juniper-nsp mailing list