A subtree filter is comprised of XML elements and their XML attributes. There are five types of components that can be present in a subtree filter:

  • Namespace Selection
  • Attribute Match Expressions
  • Containment Nodes
  • Selection Nodes
  • Content Match Nodes

Common scenarios and examples can be found in the RFC 6241. This article provides more details on corner cases scenarios and mixed combinations of Content Match and Selection nodes scenarios. In addition, it illustrates how missing and non matching nodes are getting handled.


Selection Nodes: an empty leaf node within a filter is called a "selection node", and it represents an "explicit selection" filter on the underlying data model. Presence of any selection nodes within a set of sibling nodes will cause the filter to select the specified subtree(s) and suppress automatic selection of the entire set of sibling nodes in the underlying data model. For filtering purposes, an empty leaf node can be declared either with an empty tag (e.g., <foo/>) or with explicit start and end tags (e.g., <foo> </foo>). Any whitespace characters are ignored in this form.


Content Match Nodes: a leaf node that contains simple content is called a "content match node". It is used to select some or all of its sibling nodes for filter output, and it represents an exact-match filter on the leaf node element content.


If all specified sibling content match nodes in a subtree filter expression are "true", then the filter output nodes are selected in the following manner:

  • Each content match node in the sibling set is included in the filter output
  • If any containment nodes are present in the sibling set, then they are processed further and included if any nested filter criteria are also met
  • If any selection nodes are present in the sibling set, then all of them are included in the filter output
  • If any sibling nodes of the selection node are instance identifier components for a conceptual data structure (e.g., list key leaf), then they MAY also be included in the filter output
  • Otherwise (i.e., there are no selection or containment nodes in the filter sibling set), all the nodes defined at this level in the underlying data model (and their subtrees, if any) are returned in the filter output.


If any of the sibling content match node tests are "false", then no further filter processing is performed on that sibling set, and none of the sibling subtrees are selected by the filter, including the content match node(s).



Assume we have a YANG module as follows (refer to attachments):


module subtree-test {
  yang-version 1.1;
  namespace "http://yumaworks.com/ns/subtree-test";
  prefix "subtree-test";

  revision "2020-03-03" {
      description
       "Initial test module for get2 callbacks";
  }

  container get2-state {
    config false;

    list port {
      key name;
      leaf name { type string; }

      leaf type { type string; }
      leaf nexttype { type string; }
      leaf-list ll-type { type string; }
      leaf-list ll-nexttype { type string; }

      container aug-data {
        leaf aug-type { type string; }
        leaf aug-nexttype { type string; }
        leaf-list aug-ll-type { type string; }
        leaf-list aug-ll-nexttype { type string; }
      }
    }
  }
}


Now assume that when we send <get> request on the top node the server returns (refer to attachments):


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name1</name>
                <type>some-type</type>
                <ll-type>type1</ll-type>
                <ll-type>type2</ll-type>
                <aug-ll-type>aug-type1</aug-ll-type>
                <aug-ll-type>aug-type2</aug-ll-type>
                <aug-data>
                    <aug-type>sometype</aug-type>
                    <aug-ll-type>type1</aug-ll-type>
                    <aug-ll-type>type2</aug-ll-type>
                    <aug-ll-nexttype>nexttype1</aug-ll-nexttype>
                    <aug-ll-nexttype>nexttype2</aug-ll-nexttype>
                </aug-data>
            </port>
            <port>
                <name>name2</name>
                <nexttype>some-nexttype</nexttype>
                <ll-nexttype>nexttype1</ll-nexttype>
                <ll-nexttype>nexttype2</ll-nexttype>
                <aug-ll-type>aug-type1</aug-ll-type>
                <aug-ll-type>aug-type2</aug-ll-type>
                <aug-data>
                    <aug-type>sometype</aug-type>
                    <aug-ll-type>type1</aug-ll-type>
                    <aug-ll-type>type2</aug-ll-type>
                    <aug-ll-nexttype>nexttype1</aug-ll-nexttype>
                    <aug-ll-nexttype>nexttype2</aug-ll-nexttype>
                </aug-data>
            </port>
        </get2-state>
    </data>
</output>


Note, that the two list entries have different children nodes values. This difference will affect the output result.

For example, let us look into the following example.



Specific Selection node(s) from a Non Specific Entry


The following request does not have any content-match nodes; only selection nodes, to select any entries that match name or type nodes.


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name/>     <!--key-->
                <type/>     <!-- present only in list=name1 -->
            </port>
        </get2-state>
    </filter>
</get>

As we can see from the Top level <get> request, the first list entry matches both type and name nodes, so it will be return with all these matching nodes.

For the second list entry, there is no any type nodes in the second entry; however, there is still name node in it. So the server will ignore missing type and return the second list entry as well, based on the one Selection node request.

The final output may look as follows:


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name1</name>
                <type>some-type</type>
            </port>
            <port>
                <name>name2</name>
            </port>
        </get2-state>
    </data>
</output>



Specific Selection node(s) from a Non Specific Entry 2


Now, let us look through similar request, but with out any key specified at all.

Assume the <get> request has only some selection nodes:


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <nexttype/>      <!-- present only in list=name2 -->
                <ll-type/>       <!-- present only in list=name1 -->
            </port>
        </get2-state>
    </filter>
</get>


As we can see from the Top level <get> request, the first list entry matches only ll-type nodes and because of this this node will be return. There is no any content-match in this request, so there is nothing can prune the whole list entry.

For the second list entry, there is no any ll-type nodes, but the node nexttype is present and matches the selection node.

The final output may look as follows:


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name1</name>
                <ll-type>type1</ll-type>
                <ll-type>type2</ll-type>
            </port>
            <port>
                <name>name2</name>
                <nexttype>some-nexttype</nexttype>
            </port>
        </get2-state>
    </data>
</output>



Specific Selection node(s) from a Specific Entry


The following request does have a Content Match nodes, the key node name=name2. In addition to this Content Match node it has Selection node type. The logic in the request would be to return an entry node that matches the Content Match first. If there is no such node, the return will be empty. If the Content Match node matches the filter then the server will check if the Selection node present and if there is such a node it will also include it in the output. If there is no such Selection node this node will be ignored and Content Match node will be present in the output.


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name2</name>
                <type/>
            </port>
        </get2-state>
    </filter>
</get>


As we can see from the Top level <get> request, the first list entry will not match the Content Match component in the filter and will be pruned with out any further processing. The second entry will match the Content Match component in the filter and the server will try to match Selection node, that is not present in the second entry. As a result this node will be ignored and pruned from the output.

The final output may look as follows:


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name2</name>
            </port>
        </get2-state>
    </data>
</output>



Specific Selection node(s) with Content Match node(s) from a Non Specific Entry


The following request does not have any Content Match component in the filter for a list key, meaning that this request is for any non specific list entry. However, it does have Content Match component in the filter for some leaf. As a result, the server will have to match that Content Match node first and only then try to match Selection nodes.


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name/>
                <type>some-type</type>
                <ll-type/>
            </port>
        </get2-state>
    </filter>
</get>


As we can see from the Top level <get> request, the first list entry has the Content Match node type, as a result the server will prune the second list entry since it does not match the Content Match component in the filter. Then the server will try to match the next Selection nodes name and ll-type. Both of these Selection nodes exist in this list entry, as as result the final output may look as follows:


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name1</name>
                <type>some-type</type>
                <ll-type>type1</ll-type>
                <ll-type>type2</ll-type>
            </port>
        </get2-state>
    </data>
</output>

For example, the following request will produce the same output as above:


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name/>
                <type>some-type</type>
                <ll-type/>
                <ll-nexttype/>           <!-- not matching node -->
            </port>
        </get2-state>
    </filter>
</get>


The ll-nexttype will be ignored and pruned out since it does not match Selection node component from the filter, the first list does not such a node setup. As a result the server will return the same output as for the previous request.


Specific Content Match node(s) from a Non Specific Entry


The following <get> request illustrates how to find any list entry with a specific Content Match node. In this case the server will try to match any list entry with this specific Content Match node. Note, that this node is within a container and the server will output all its siblings as well.


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <aug-data>
                    <aug-type>sometype</aug-type>
                </aug-data>
            </port>
        </get2-state>
    </filter>
</get>


As we can see from the Top level <get> request, both list entries match the Content Match component in the filter, as a result the server will output both entries. There is no any Selection nodes in the filter, so there is nothing to filter out and the output will contain all the siblings of the Content Match node. The final output may look as follows:


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name1</name>
                <aug-data>
                    <aug-type>sometype</aug-type>
                    <aug-ll-type>type1</aug-ll-type>
                    <aug-ll-type>type2</aug-ll-type>
                    <aug-ll-nexttype>nexttype1</aug-ll-nexttype>
                    <aug-ll-nexttype>nexttype2</aug-ll-nexttype>
                </aug-data>
            </port>
            <port>
                <name>name2</name>
                <aug-data>
                    <aug-type>sometype</aug-type>
                    <aug-ll-type>type1</aug-ll-type>
                    <aug-ll-type>type2</aug-ll-type>
                    <aug-ll-nexttype>nexttype1</aug-ll-nexttype>
                    <aug-ll-nexttype>nexttype2</aug-ll-nexttype>
                </aug-data>
            </port>
        </get2-state>
    </data>
</output>



Specific Selection node(s) from a Non Specific Entry


The following <get> request illustrates how to find any list entry with a specific Selection node. In this case the server will try to match any list entry with this specific Selection node. Note, that this node is within a container but now the server will NOT output all its siblings since this is the Selection node filtering.


<get>
    <filter type="subtree">
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <type/>
                <aug-data>
                    <aug-ll-type/>
                </aug-data>
            </port>
        </get2-state>
    </filter>
</get>


As we can see from the Top level <get> request, only the first entry matches both Selection nodes type and aug-ll-type and it will be included in the output with all of them in it. The second list entry will also be included in the output because there is no any Content Match nodes but only Selection nodes. Since it matches the second Selection node component from the filter (aug-ll-type) it will be included in the output but with out type node it it.

The final output may look as follows:


<output xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <get2-state xmlns="http://yumaworks.com/ns/subtree-test">
            <port>
                <name>name1</name>
                <type>some-type</type>
                <aug-data>
                    <aug-ll-type>type1</aug-ll-type>
                    <aug-ll-type>type2</aug-ll-type>
                </aug-data>
            </port>
            <port>
                <name>name2</name>
                <aug-data>
                    <aug-ll-type>type1</aug-ll-type>
                    <aug-ll-type>type2</aug-ll-type>
                </aug-data>
            </port>
        </get2-state>
    </data>
</output>

Note, that there is no any extra nodes in the aug-data container. This is because the filter has only Selection nodes components. Refer to the definition of Selection node component in the beginning of this article.