Skip to content

RelaxNG XML-syntax parser does not traverse <div> when collecting <define>s #52

Description

@casoon

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions