Subject: [netmod] I-D Action: draft-ietf-netmod-rfc6020bis-07.txt

From: [email-masked]
Date: Wed, 23 Sep 2015 00:13:22 -0700

A New Internet-Draft is available from the on-line Internet-Drafts directories.
 This draft is a work item of the NETCONF Data Modeling Language Working Group of the IETF.

        Title           : The YANG 1.1 Data Modeling Language
        Author          : Martin Bjorklund
	Filename        : draft-ietf-netmod-rfc6020bis-07.txt
	Pages           : 196
	Date            : 2015-09-23

Abstract:
   YANG is a data modeling language used to model configuration data,
   state data, remote procedure calls, and notifications for network
   management protocols like the Network Configuration Protocol
   (NETCONF).

The IETF datatracker status page for this draft is:
https://datatracker.ietf.org/doc/draft-ietf-netmod-rfc6020bis/

There's also a htmlized version available at:
https://tools.ietf.org/html/draft-ietf-netmod-rfc6020bis-07

A diff from the previous version is available at:
https://www.ietf.org/rfcdiff?url2=draft-ietf-netmod-rfc6020bis-07

Please note that it may take a couple of minutes from the time of submission
until the htmlized version and diff are available at tools.ietf.org.

Internet-Drafts are also available by anonymous FTP at:
ftp://ftp.ietf.org/internet-drafts/

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 23 Sep 2015 09:17:41 +0200 (CEST)

Hi,

This version addresses the last open issue Y60, and contains fixes for
hopefully all WG comments so far.  I believe that this version is
ready for WGLC.

/martin

[email-masked] wrote:
> _______________________________________________
> netmod mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/netmod
>

---

From: Jernej Tuljak <[email-masked]>
Date: Wed, 23 Sep 2015 11:45:19 +0200

Section 7.21.5., the first bullet describing the augmentation case does 
not consider that an "augment" may specify a top-level "choice" or a 
"choice"/"case" nested within a top-level "choice" as the target node. 
There will be no initial context node for the expression in such a case.

   leaf enable-foos {
     type boolean;
   }
   choice ch1 {
     case foo {
       choice foos {
         when "enable-foos = 'true'";
         leaf foo1 {
           type string;
         }
         leaf foo2 {
           type string;
         }
       }
     }
     container meh;
   }

   augment "/ch1/foo/foos" {
     when "enable-foos = 'true'";
     leaf foo3 {
       type string;
     }
   }

OLD:

    o  If the "when" statement is a child of an "augment" statement, then
       the context node is the augment's target node in the data tree, if
       the target node is a data node.  Otherwise, the context node is
       the closest ancestor node to the target node that is also a data
       node.

NEW:

    o  If the "when" statement is a child of an "augment" statement, then
       the context node is the augment's target node in the data tree, if
       the target node is a data node.  Otherwise, the context node is
       the closest ancestor node to the target node that is also a data
       node. If no such node exists, the context node is the root node.

Jernej

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Sep 2015 11:58:58 +0200

> On 23 Sep 2015, at 11:45, Jernej Tuljak <[email-masked]> wrote:
> 
> Section 7.21.5., the first bullet describing the augmentation case does not consider that an "augment" may specify a top-level "choice" or a "choice"/"case" nested within a top-level "choice" as the target node. There will be no initial context node for the expression in such a case.
> 
>  leaf enable-foos {
>    type boolean;
>  }
>  choice ch1 {
>    case foo {
>      choice foos {

Good catch, I support this change.

Also regarding sec. 7.21.5, I think we agreed that a when expression must not reference nodes that are made conditional through that when statement. I can’t find this rule in the text.

Lada 

--
Ladislav Lhotka, CZ.NIC Labs
PGP Key ID: E74E8C0C

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 23 Sep 2015 12:34:10 +0200 (CEST)

Jernej Tuljak <[email-masked]> wrote:
> Section 7.21.5., the first bullet describing the augmentation case
> does not consider that an "augment" may specify a top-level "choice"
> or a "choice"/"case" nested within a top-level "choice" as the target
> node. There will be no initial context node for the expression in such
> a case.
> 
>   leaf enable-foos {
>     type boolean;
>   }
>   choice ch1 {
>     case foo {
>       choice foos {

Agreed.  I have updated the text with this change.  Thanks!

/martin

---

From: Jernej Tuljak <[email-masked]>
Date: Wed, 23 Sep 2015 12:37:48 +0200

> Also regarding sec. 7.21.5, I think we agreed that a when expression must not reference nodes that are made conditional through that when statement. I can’t find this rule in the text.

The "no referencing the initial context node and its descendants" text 
is currently in the guidelines draft only (6087bis).

Jernej

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Sep 2015 12:52:12 +0200

> On 23 Sep 2015, at 12:37, Jernej Tuljak <[email-masked]> wrote:
> 
> The "no referencing the initial context node and its descendants" text is currently in the guidelines draft only (6087bis).

IMO this should be a hard rule in 6020bis. Such expressions are seriously broken and could lead to deadlocks.

Lada

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 23 Sep 2015 13:07:09 +0200 (CEST)

Ladislav Lhotka <[email-masked]> wrote:
> >> Also regarding sec. 7.21.5, I think we agreed that a when expression
> >> must not reference nodes that are made conditional through that when
> >> statement. I can’t find this rule in the text.
> > 
> IMO this should be a hard rule in 6020bis. Such expressions are
> seriously broken and could lead to deadlocks.

This reminds me of Juergen's golden rule: "All implementations of this
spec MUST be bug-free".  We'd have to say "all XPath expressions MUST
make sense".

Referencing nodes that don't exist is legal XPath, but it probably
does not make much sense.

/martin

---

From: Jernej Tuljak <[email-masked]>
Date: Wed, 23 Sep 2015 13:06:57 +0200

> IMO this should be a hard rule in 6020bis. Such expressions are seriously broken and could lead to deadlocks.

I think that was the purpose of the change in 3rd bullet. A "dummy" node 
with no value and child nodes has been introduced.

    o  If the "when" statement is a child of any other data definition
       statement, the accessible tree is tentatively altered during the
       processing of the XPath expression by replacing all instances (if
       any) of the data node for which the "when" statement is defined
       with a single dummy node with the same name, but with no value and
       no children.  The context node is this dummy node.

Jernej

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Sep 2015 14:21:04 +0200

> spec MUST be bug-free".  We'd have to say "all XPath expressions MUST

Of course this is very different. An XPath expression that doesn’t make
sense represents no problem whatsoever as long as the result can be
reliably determined.

What we (potentially) have here is this: the server evaluates an
expression, then changes the datastore schema based on the result,
deletes some instances from the datastore, but after this the XPath
expression gives a different result. This IMO indicates that it's
something rotten with the definition of "when".

>does not make much sense.

It's more complicated than this because of other YANG-specific rules.

container foo {
  when "not(enabled = 'false')";
  leaf enabled {
    type boolean;
    default false;
  }
}

If there is no "foo" in the datastore, then the procedure from the third
bullet in sec. 7.21.5 leads to the result that the when expression is
true, so "foo" is valid and the default value for "enabled" comes into
play, which however makes the when expression evaluate to false.

Lada

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Sep 2015 14:29:15 +0200

> with no value and child nodes has been introduced.

Not really, the dummy node solves the problem of a non-existent context
node. If the when expression refers to the value or descendants of the
dummy node, then the procedure is ill-defined, see my response to
Martin.

Lada

---

From: Jernej Tuljak <[email-masked]>
Date: Wed, 23 Sep 2015 15:08:18 +0200

> play, which however makes the when expression evaluate to false.

This is not how I read it. 3rd bullet makes your expression _always_ 
evaluate to the same boolean value, since there is no "enabled" child 
node to "foo" during evaluation, ever. It will never be present in the 
accessible tree, since it is pruned away before evaluation 
(child::enabled always returns an empty node-set no matter what is in 
your datastore).

Jernej

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Sep 2015 15:13:36 +0200

> On 23 Sep 2015, at 15:08, Jernej Tuljak <[email-masked]> wrote:
> 
> This is not how I read it.

Well, I significantly contributed to this formulation. :-)

> 3rd bullet makes your expression _always_ evaluate to the same boolean value, since there is no "enabled" child node to "foo" during evaluation, ever. It will never be present in the accessible tree, since it is pruned away before evaluation (child::enabled always returns an empty node-set no matter what is in your datastore).

Are you saying that the data tree

"foo": { "enabled" : false }

is valid?

Lada

---

From: Jernej Tuljak <[email-masked]>
Date: Wed, 23 Sep 2015 15:38:18 +0200

> "foo": { "enabled" : false }

Yes. And so would be:

"foo": { "enabled" : true }

In XPath 1.0 spec language (Section 3.4):

If one object to be compared is a node-set and the other is a string, 
then the comparison will be true if and only if there is a node in the 
node-set such that the result of performing the comparison on the 
string-value 
<http://www.w3.org/TR/1999/REC-xpath-19991116/#dt-string-value>of the 
node and the other string is true

meaning that

enabled = 'false'

always evaluates to boolean false, since the node-set will always be 
empty, no matter what you do.

 From the expression context point of view, your expression could be 
changed to:

not(enabled1 = 'false')
not(enabled2 = 'false')
not(enabled3 = 'false')
...
not(enabledN = 'false')

but that would make no difference, since the context node (foo) will 
never have any children. You can no longer reference descendants of the 
context node, nor its value (unless it's the document root) in when 
expressions.

If you take the negation away in your example, your instance will never 
be valid, however.

Jernej

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Sep 2015 16:22:04 +0200

> On 23 Sep 2015, at 15:38, Jernej Tuljak <[email-masked]> wrote:
> 

Yuck! Maybe the third bullet can be interpreted this way but I think it is very confusing because sec. 7.21.5 also says:

The node defined by the parent data definition statement is only valid when the condition specified by the "when" statement is satisfied.

Note that my argument and example also apply to when appearing on an augment, and the third bullet doesn’t cover to this case.

Lada

> If one object to be compared is a node-set and the other is a string, then the comparison will be true if and only if there is a node in the node-set such that the result of performing the comparison on thestring-value of the node and the other string is true
> 
> meaning that 
> enabled = 'false'
> always evaluates to boolean false, since the node-set will always be empty, no matter what you do.
> 
> From the expression context point of view, your expression could be changed to:
> not(enabled1 = 'false')
> not(enabled2 = 'false')
> not(enabled3 = 'false')
> ...
> not(enabledN = 'false')
> 
> 
> but that would make no difference, since the context node (foo) will never have any children. You can no longer reference descendants of the context node, nor its value (unless it's the document root) in when expressions.
> 
> If you take the negation away in your example, your instance will never be valid, however.
> 
> Jernej
> 
>> Lada
>> 
>> 
>>> Jernej
>>> 
>>> 
>>>> Lada
>>>> 
>>>> 
>>>>> /martin
>>>>> 
>> --

---

From: Jernej Tuljak <[email-masked]>
Date: Thu, 24 Sep 2015 11:13:40 +0200

> Not really, the dummy node solves the problem of a non-existent context

Are you referring to "existence" in the instance document or the schema 
tree? Why is there no need for "no children, no value dummy" in 1st and 
2nd bullet?

Jernej

> If the when expression refers to the value or descendants of the

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 24 Sep 2015 13:54:49 +0200 (CEST)

Jernej Tuljak <[email-masked]> wrote:
> Are you referring to "existence" in the instance document or the
> schema tree? Why is there no need for "no children, no value dummy" in
> 1st and 2nd bullet?

In these cases, the context node is well-defined anyway.  But I think
that also these bullets need to have text that make sure that the
outcome is deterministic in all cases, such as:

  augement /foo {
    when "bar > 1";
    leaf bar { type int32; }
  }

or

  grouping foo {
    leaf bar { type int32; }
  }
  container x {
    uses foo {
      when "bar > 1";
    }
  }

etc.

So I suggest this NEW text:

   o  If the "when" statement is a child of an "augment" statement, then
      the context node is the augment's target node in the data tree, if
      the target node is a data node.  Otherwise, the context node is
      the closest ancestor node to the target node that is also a data
      node.  If no such node exists, the context node is the root node.
      The accessible tree is tentatively altered during the processing
      of the XPath expression by removing all instances (if any) of the
      nodes added by the "augment" statement.

   o  If the "when" statement is a child of a "uses", "choice", or
      "case" statement, then the context node is the closest ancestor
      node to the "uses", "choice", or "case" node that is also a data
      node.  If no such node exists, the context node is the root node.
      The accessible tree is tentatively altered during the processing
      of the XPath expression by removing all instances (if any) of the
      nodes added by the "uses", "choice", or "case" statement.

/martin

---

From: Jernej Tuljak <[email-masked]>
Date: Thu, 24 Sep 2015 14:47:58 +0200

>        no children.  The context node is this dummy node.

+1

   container foo {
     when "child::* or child::text() or not(self::*)"; // always false
     leaf bar {
       type string;
     }
   }

Jernej

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 25 Sep 2015 09:58:16 +0200

>      when "child::* or child::text() or not(self::*)"; // always false

I think it would be better to clearly state that a "when" expression
MUST NOT refer to nodes that are made conditional by the same "when"
statement - it's similar to the rule that forbids mutual references.
This would also cover all uses of "when".

The above example would be really confusing if the "bar" instance is
present. I also don't like the fact that "when" and "must" would give
different results in this case.

Lada

---

From: Jernej Tuljak <[email-masked]>
Date: Fri, 25 Sep 2015 13:25:05 +0200

Ladislav Lhotka je 25.9.2015 ob 9:58 napisal:
> present.

It is true that this introduces a caveat that is bound to confuse end 
YANG users.

>   I also don't like the fact that "when" and "must" would give

Just to be clear, you would like this, right?

NEW:

    The XPath expression is conceptually evaluated in the following
    context, in addition to the definition inSection 6.4.1 
<https://tools.ietf.org/html/draft-ietf-netmod-rfc6020bis-07#section-6.4.1>:

    o  If the "when" statement is a child of any other data definition
       statement, the context node is the node in the accessible tree for
       which the "when" statement is defined.
    
    An XPath expression MUST NOT reference nodes that are made conditional
    by the "when" statement that defines it.

I don't see a case in which the context node is non-existent (in the 
schema tree) in any of the three bullets, even without "no value, no 
descendants" dummy node.

This text implies that:

   container foo {
     when "descendant-or-self::node()"; // semantic error
     leaf bar {
       type string;
     }
   }

This is actually what our YANG 1.0 implementation currently does, though 
it only generates a warning.

Jernej

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 25 Sep 2015 13:41:10 +0200 (CEST)

> This would also cover all uses of "when".

So what does this mean:

  augment /a/b/c {
    when "* = 42";
    leaf foo {
      type int32;
    }
  }

Is this an error, since the "*" references a node made conditional?

> different results in this case.

I agree, but OTOH we're talking about a theoretical corner case.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 25 Sep 2015 13:44:39 +0200

>     by the "when" statement that defines it.

Yes, plus the other two rules that are already in 6020bis:

If the XPath expression references any node that also has associated
"when" statements, these "when" expressions MUST be evaluated first.

There MUST NOT be any circular dependencies in these "when" expressions.
> schema tree) in any of the three bullets, even without "no value, no 

The third bullet is aimed at cases like this:

leaf foo {
    when "../bar > 0";
    mandatory true;
    ...
}

If there is no instance of "foo", a validator has to find out whether
the "mandatory" statement applies (and the absence of "foo" is thus a
schema error), or whether it is overruled by the "when" expression being
false. But in order to be able to evaluate that expression, XPath
requires a context node in the instance document, so we need to
tentatively add one.

Lada

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 25 Sep 2015 13:57:28 +0200

> On 25 Sep 2015, at 13:41, Martin Bjorklund <[email-masked]> wrote:
> 

Yes, because the nodeset represented by * includes the child “foo”.

> I agree, but OTOH we're talking about a theoretical corner case.

For “must” no such restrictions exist (circular references are OK, too), and YANG beginners often don’t get the subtle difference between “must” and “when”.

Lada

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 25 Sep 2015 14:03:12 +0200 (CEST)

> Yes, because the nodeset represented by * includes the child “foo”.

Well, if "foo" doesn't exist, "*" obviously does not include "foo".
So this would mean that depending on when this expression is
evaluated, it may or may not be illegal...

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 25 Sep 2015 14:21:29 +0200

> evaluated, it may or may not be illegal...

This is a consequence of the fact that we are using results of XPath
expressions (that can only be evaluated in the context of a concrete
instance document) for modifying the schema.

I could similarly ask whether this is a circular reference if either
"foo" or "bar" instance doesn't exist:

leaf foo {
  when "not(../bar)";
  ...
}

leaf bar {
  when "not(../foo)";
  ...
}

Yes, we are on a rather slippery slope here.

Lada

---

From: Jernej Tuljak <[email-masked]>
Date: Fri, 25 Sep 2015 15:15:32 +0200

> requires a context node in the instance document, so we need to

Then the dummy node text is broken all together. It instructs to modify 
the accessible tree (schema), instead of instructing to instantiate a 
dummy if an instance of the context node does not exist. A context node 
always exists in the schema tree. IMO, this needs to be fixed in order 
to prevent the interpretation I came up with (and also Balazs, 
independently). This interpretation was clearly not the intention.

NEW:

       
    If an instance of the context node does not exist during processing
    of the XPath expression, the context node is tentatively instantiated
    as a single dummy node with the same name, but with no value and no
    children, and merged into the instance of the accessible tree.

    The result of the XPath expression is converted to a boolean value
    using the standard XPath rules.

    There MUST NOT be any circular dependencies in these "when"
    expressions.

Something like this also takes care of Martin's example ("* = 42").

Jernej

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 25 Sep 2015 15:22:24 +0200 (CEST)

Jernej Tuljak <[email-masked]> wrote:
> >>>>>>>>>>>>        o If the "when" statement is a child of an "augment"
> >>>>>>>>>>>>        statement,
> >>>>>>>>>>>>        then
> >>>>>>>>>>>>           the context node is the augment's target node in the
> >>>>>>>>>>>>           data tree,
> >>>>>>>>>>>>           if
> >>>>>>>>>>>>        o If the "when" statement is a child of an "augment"
> >>>>>>>>>>>>        statement,
> >>>>>>>>>>>>        then
> >>>>>>>>>>>>           the context node is the augment's target node in the
> >>>>>>>>>>>>           data tree,
> >>>>>>>>>>>>           if
> Then the dummy node text is broken all together. It instructs to
> modify the accessible tree (schema)

The accessible tree is not the schema, it is the instance data.

> instead of instructing to
> instantiate a dummy if an instance of the context node does not
> exist.

No, the text says *replace* any instances with the dummy instance;
this ensures that the result is the same regardless of if the node
exists or not.

> A context node always exists in the schema tree.

The context node is in the data tree.

> IMO, this
> needs to be fixed in order to prevent the interpretation I came up
> with (and also Balazs, independently). This interpretation was clearly
> not the intention.
> 
> NEW:
> 

How?  It is not clear to me if the '*' is legal or not.

/martin

---

From: Jernej Tuljak <[email-masked]>
Date: Fri, 25 Sep 2015 17:00:34 +0200

> this ensures that the result is the same regardless of if the node

Okay, the accessible tree is instantiated data nodes.

container top {
     leaf foo {
         when "../bar > 0";
         mandatory true;
         ...
     }
}

"top": {}

"top": { "foo": "" }

How is a context node ensured for the two instances, if replacing 
something that may not exist? You would need to create a dummy if there 
is no "foo" instance, right? The text only says "replace".

> How?  It is not clear to me if the '*' is legal or not.

It just occurred to me that it is very hard to not reference the context 
node in a "when" XPath expression, since the context node is always your 
initial XPath context (you always start with a node-set of size 1, 
containing the context node).

"../bar" says, select the parent of the context node, then select "bar" 
child
"*" says, select the children of the context node that are also element 
nodes

So, yeah, "MUST NOT reference conditional nodes" doesn't work.

Jernej

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 28 Sep 2015 12:15:27 +0200 (CEST)

Jernej Tuljak <[email-masked]> wrote:
> >>>>>>>>>>>>>> node. There will be no initial context node for the expression
> >>>>>>>>>>>>>> in
> >>>>>>>>>>>>>> such
> >>>>>>>>>>>>>> a case.
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>>        leaf enable-foos {
> >>>>>>>>>>>>>>          type boolean;
> >>>>>>>>>>>>>>        }
> >>>>>>>>>>>>>>        choice ch1 {
> >>>>>>>>>>>>>>          case foo {
> >>>>>>>>>>>>>>            choice foos {
> >>>>>>>>>>>>>>            the target node is a data node.  Otherwise, the
> >>>>>>>>>>>>>>            context
> >>>>>>>>>>>>>>            node is
> >>>>>>>>>>>>>>            the target node is a data node.  Otherwise, the
> >>>>>>>>>>>>>>            context
> >>>>>>>>>>>>>>            node is
> >>>>>>>>>>>>>>            node. If no such node exists, the context node is
> >>>>>>>>>>>>>>            the
> >>>>>>>>>>>>>>            root node.
> >>>>>>>>>>>>>>
> >>>>>>>           the context node is the augment's target node in the data
> >>>>>>>           tree,
> >>>>>>>           if
> >>>>>>>           of the XPath expression by removing all instances (if any)
> >>>>>>>           of
> >>>>>>>           the
> >>>>>>>           of the XPath expression by removing all instances (if any)
> >>>>>>>           of
> >>>>>>>           the
> >>>>>>>           processing of the XPath expression by replacing all
> >>>>>>>           instances
> >>>>>>>           (if
> >>>>>>>           with a single dummy node with the same name, but with no
> >>>>>>>           value
> >>>>>>>           and
> something that may not exist? You would need to create a dummy if
> there is no "foo" instance, right? The text only says "replace".

Ok; the intention was "replace if it exists, and create otherwise"
(i.e., "replace" as in NETCONF edit operation).   We can make this
explicit:

NEW:

- If the "when" statement is a child of any other data definition
  statement, the accessible tree is tentatively altered during the
  processing of the XPath expression by replacing all instances of the
  data node for which the "when" statement is defined with a single
  dummy node with the same name, but with no value and no children.
  If no instances of the data node exists, the dummy node is created.
  The context node is this dummy node.

> It just occurred to me that it is very hard to not reference the
> context node in a "when" XPath expression, since the context node is
> always your initial XPath context (you always start with a node-set of
> size 1, containing the context node).
> 
> "../bar" says, select the parent of the context node, then select
> "bar" child
> "*" says, select the children of the context node that are also
> element nodes
> 

So do you think that my proposed text about "tentatively remove all
conditional nodes" works?

/martin

---

From: Jernej Tuljak <[email-masked]>
Date: Mon, 28 Sep 2015 13:56:15 +0200

>    The context node is this dummy node.

I agree with this.

> conditional nodes" works?

Not sure anymore:

   grouping foo {
     leaf mandatory-foo1 {
       type string;
       mandatory true;
     }
   }

   container top {
     leaf enable {
       type boolean;
     }
     container foo {
       uses foo {
         when "../enable = 'true'";
       }
     }
   }

   augment "/top/foo" {
     when "../enable = 'true'";
     leaf mandatory-foo2 {
       type string;
       mandatory true; // local augment
     }
   }

For the following instance:

"top": { "enable": "true" }

Note that the context node (container "foo") does not exist. You'd have 
to create if not exists (+remove nodes from grouping, choice, case, 
augment if any).

Jernej

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 28 Sep 2015 14:51:23 +0200 (CEST)

> Note that the context node (container "foo") does not exist.

It actually exists, since all NP-containers exists, according to:

   If a node that exists in the accessible tree has a non-presence
   container as a child, then the non-presence container also exists in
   the tree.

/martin

---

From: Jernej Tuljak <[email-masked]>
Date: Mon, 28 Sep 2015 15:08:43 +0200

>     container as a child, then the non-presence container also exists in

Missed that. The text you proposed should be fine then. Takes care of 
both problems, the missing context node and references to conditional 
nodes in one go.

Jernej