为什么pyang在这种情况下不会抛出错误

why pyang does not throw error in this scenario

以下条件指的是不存在的节点。我想知道为什么 pyang 不抛出错误?确实如此,如果我使用了错误的前缀。

请您查看 when 条件(嵌入在模块中)。

是否允许(在 when 表达式中)从扩充本身引用模式?

module mod-w-1 {
  namespace "http://example.org/tests/mod-w-1";
  prefix m1;

  container m1 {
    leaf b1 {
      type string;
    }
  }
}

module when-tests {
  namespace "http://example.org/tests/when-tests";
  prefix wt;

  import mod-w-1 {
    prefix m1;
  }

  augment "/m1:m1" {
       // when "/m1:m1/b3 = 'abc'";
       // there is no b3, so, should be invalid.

       // when "/m1:m1/b1 = 'abc'";
       // a payload or data situation that has m1/b1 != 'abc' will cause the 
       // data that fits this augment content will be invalid/rejected.
       /* for ex; 
          <m1>
            <b1>fff</b1>
            <x>sfsf</x>
            <conditional>
              <foo>dddd</foo>
            </conditional>  
          </m1>
          is invalid, hence, the <x> and <conditional> parts will be 
          rejected.
      */   
       leaf x {
         type string;
       }
       container conditional {
          leaf foo {
              type string;
          }
       }
    } 
}

这是因为 pyang 根本不验证 XPath 表达式的语义,只验证它们的语法 - 以及一些额外的检查,例如函数和前缀的使用。您将需要另一个 YANG 编译器来正确验证它们。

def v_xpath(ctx, stmt):
    try:
        toks = xpath.tokens(stmt.arg)
        for (tokname, s) in toks:
            if tokname == 'name' or tokname == 'prefix-match':
                i = s.find(':')
                if i != -1:
                    prefix = s[:i]
                    prefix_to_module(stmt.i_module, prefix, stmt.pos,
                                     ctx.errors)
            elif tokname == 'literal':
                # kind of hack to detect qnames, and mark the prefixes
                # as being used in order to avoid warnings.
                if s[0] == s[-1] and s[0] in ("'", '"'):
                    s = s[1:-1]
                    i = s.find(':')
                    # make sure there is just one : present
                    if i != -1 and s[i+1:].find(':') == -1:
                        prefix = s[:i]
                        # we don't want to report an error; just mark the
                        # prefix as being used.
                        my_errors = []
                        prefix_to_module(stmt.i_module, prefix, stmt.pos,
                                         my_errors)
                        for (pos, code, arg) in my_errors:
                            if code == 'PREFIX_NOT_DEFINED':
                                err_add(ctx.errors, pos,
                                        'WPREFIX_NOT_DEFINED', arg)
            elif ctx.lax_xpath_checks == True:
                pass
            elif tokname == 'variable':
                err_add(ctx.errors, stmt.pos, 'XPATH_VARIABLE', s)
            elif tokname == 'function':
                if not (s in xpath.core_functions or
                        s in yang_xpath_functions or
                        (stmt.i_module.i_version != '1' and
                         s in yang_1_1_xpath_functions) or
                        s in extra_xpath_functions):
                    err_add(ctx.errors, stmt.pos, 'XPATH_FUNCTION', s)
    except SyntaxError as e:
        err_add(ctx.errors, stmt.pos, 'XPATH_SYNTAX_ERROR', e)

statements.py 的 1993 行。

请注意,从 XPath 规范的角度来看,引用不存在节点的 XPath 表达式在技术上并非无效。这只是意味着位置路径将选择一个空节点集(并且您的条件将永远是false)。

是的,您可以引用 "above" 扩充的目标节点或其兄弟节点 - 事实上,当 when 语句正在运行时,您总是应该引用(它不应该引用任何有条件的节点)。

此外,您永远不应尝试使用非前缀节点测试(例如 b3b1)来破坏 "module confinement"。 XPath 表达式只能看到在定义模块和定义模块本身的导入中定义的名称。例如,即使 b3 后来被某个未知的第三个模块扩充,您的条件仍然会评估为 false。最好假定非前缀名称属于定义模块的命名空间。