The relaxng package compiles RELAX NG grammars and validates XML documents
against them.
Import path: github.com/lestrrat-go/helium/relaxng
package examples_test
import (
"context"
"fmt"
"github.com/lestrrat-go/helium"
"github.com/lestrrat-go/helium/relaxng"
)
func Example_relaxng_validate() {
p := helium.NewParser()
// Compile a small RELAX NG schema from XML syntax.
schemaDoc, err := p.Parse(context.Background(), []byte(
`<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
<element name="book">
<element name="title"><text/></element>
</element>
</start>
</grammar>`))
if err != nil {
fmt.Printf("schema parse failed: %s\n", err)
return
}
grammar, err := relaxng.NewCompiler().Compile(context.Background(), schemaDoc)
if err != nil {
fmt.Printf("schema compile failed: %s\n", err)
return
}
doc, err := p.Parse(context.Background(), []byte(`<book><title>Helium</title></book>`))
if err != nil {
fmt.Printf("xml parse failed: %s\n", err)
return
}
// Create a validator from the compiled grammar. Label sets the
// document name used in error messages (it does not read from disk).
v := relaxng.NewValidator(grammar).
Label("doc.xml")
if err := v.Validate(context.Background(), doc); err != nil {
fmt.Println(err)
}
// Output:
}source: examples/relaxng_validate_example_test.go
The compiler is secure by default: schemas referenced by include and
externalRef are loaded through a deny-all filesystem, so an untrusted grammar
cannot read host files. To allow loading, supply a filesystem explicitly —
either a confined fs.FS rooted at a trusted directory, or
helium.PermissiveFS() to restore the historical os.Open behavior:
grammar, err := relaxng.NewCompiler().
FS(helium.PermissiveFS()). // or a confined fs.FS
CompileFile(ctx, "schema.rng")Each include/externalRef target is also read under a per-resource byte cap
(10 MiB by default, configurable via Compiler.MaxResourceBytes); a target that
exceeds the cap fails to load instead of being read in full.