Summary
parse_relaxng (src/validation/relaxng.rs) builds its define/symbol table
by scanning the direct children of <grammar>, but does not recurse into
<div> wrapper elements. Per the RELAX NG spec, <div> is purely
organizational — <define>s nested inside a <div> belong to the
enclosing <grammar>'s single flat symbol table, exactly like a top-level
<define>.
As a result, any <define> nested inside one or more <div> levels is
invisible to name resolution, and a <ref name="..."> pointing to it fails
with undefined reference: ... even though the definition is present in
the document.
This shows up in practice when flattening a modular RELAX NG schema (e.g.
via rnginline, which resolves <include>/<externalRef> by wrapping
each resolved module's content in a <div>) into a single file for
xmloxide to consume — the flattener's output is spec-valid RNG, but
xmloxide can't resolve refs into it until the <div> wrappers are
manually stripped/unwrapped first.
Reproduction
use xmloxide::validation::relaxng::parse_relaxng;
let schema = parse_relaxng(r#"
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start><ref name="root"/></start>
<div>
<define name="root"><element name="root"><empty/></element></define>
</div>
</grammar>
"#).unwrap();
Expected: schema parses and can validate <root/>.
Actual: fails (or, if parse_relaxng itself succeeds, validate errors
with undefined reference: root) because the <define> inside <div>
was never collected.
Suggested fix
When collecting <define> children of <grammar> (and recursively for
nested <div>s), treat <div> as transparent: recurse into it and
collect its <define>/<start> children into the same enclosing scope,
per RELAX NG §4.16 ("div").
Context
Found while vendoring the W3C/WHATWG HTML5 RELAX NG schema from
validator/validator (the Nu Html Checker) for
https://github.com/casoon/html-conform — that schema is naturally modular
(19 included sub-grammars) and any general-purpose flattening tool
produces <div>-wrapped output.
xmloxide version: 0.5.0
Summary
parse_relaxng(src/validation/relaxng.rs) builds its define/symbol tableby scanning the direct children of
<grammar>, but does not recurse into<div>wrapper elements. Per the RELAX NG spec,<div>is purelyorganizational —
<define>s nested inside a<div>belong to theenclosing
<grammar>'s single flat symbol table, exactly like a top-level<define>.As a result, any
<define>nested inside one or more<div>levels isinvisible to name resolution, and a
<ref name="...">pointing to it failswith
undefined reference: ...even though the definition is present inthe document.
This shows up in practice when flattening a modular RELAX NG schema (e.g.
via
rnginline, which resolves<include>/<externalRef>by wrappingeach resolved module's content in a
<div>) into a single file forxmloxideto consume — the flattener's output is spec-valid RNG, butxmloxidecan't resolve refs into it until the<div>wrappers aremanually stripped/unwrapped first.
Reproduction
Expected: schema parses and can validate
<root/>.Actual: fails (or, if
parse_relaxngitself succeeds,validateerrorswith
undefined reference: root) because the<define>inside<div>was never collected.
Suggested fix
When collecting
<define>children of<grammar>(and recursively fornested
<div>s), treat<div>as transparent: recurse into it andcollect its
<define>/<start>children into the same enclosing scope,per RELAX NG §4.16 ("div").
Context
Found while vendoring the W3C/WHATWG HTML5 RELAX NG schema from
validator/validator(the Nu Html Checker) forhttps://github.com/casoon/html-conform — that schema is naturally modular
(19 included sub-grammars) and any general-purpose flattening tool
produces
<div>-wrapped output.xmloxide version: 0.5.0