Skip to content

Latest commit

 

History

History
79 lines (64 loc) · 2.32 KB

File metadata and controls

79 lines (64 loc) · 2.32 KB

relaxng

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

Loading external schemas (include / externalRef)

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.