nowhere near usable but setting aside for rainy day
This commit is contained in:
parent
5e9399497b
commit
9d59974e5a
2
conf.go
2
conf.go
@ -1,4 +1,4 @@
|
|||||||
package conf
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
12
const.go
12
const.go
@ -1,6 +1,14 @@
|
|||||||
package conf
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XSIVal = "http://www.w3.org/2001/XMLSchema-instance"
|
XSIVal = "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
DefSchemaNS = "xsi"
|
DefSchemaNS = "xsi"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
uriRe = regexp.MustCompile(`^(?P<type>file|https?)://(?P<path>.+)$`)
|
||||||
|
)
|
||||||
|
128
func_nsxml.go
Normal file
128
func_nsxml.go
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
lxml "github.com/lestrrat-go/libxml2"
|
||||||
|
lxmlp "github.com/lestrrat-go/libxml2/parser"
|
||||||
|
lxmlt "github.com/lestrrat-go/libxml2/types"
|
||||||
|
"github.com/lestrrat-go/libxml2/xsd"
|
||||||
|
rpaths "r00t2.io/sysutils/paths"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewNsXml(raw *[]byte) (x *NsXml, err error) {
|
||||||
|
|
||||||
|
var xml NsXml
|
||||||
|
|
||||||
|
xml.Raw = raw
|
||||||
|
|
||||||
|
x = &xml
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NsXml) Validate(defaults bool) (bool, error) {
|
||||||
|
// We need the XSD before we can validate.
|
||||||
|
if err := x.getXSD(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NsXml) getXSD() error {
|
||||||
|
if err := x.mapNS(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r := uriRe.FindStringSubmatch(strings.ToLower(x.XSD.XSDPath))
|
||||||
|
reResults := make(map[string]string)
|
||||||
|
for i, name := range uriRe.SubexpNames() {
|
||||||
|
if i != 0 && name != "" {
|
||||||
|
reResults[name] = r[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var xsdRaw []byte
|
||||||
|
switch reResults["type"] {
|
||||||
|
case "file":
|
||||||
|
p := reResults["path"]
|
||||||
|
exists, err := rpaths.RealPathExists(&p)
|
||||||
|
if (err != nil) || (!exists) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
xsdRaw, err = ioutil.ReadFile(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "http", "https":
|
||||||
|
resp, err := http.Get(x.XSD.XSDPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
xsdRaw, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return errors.New("invalid URI type for schemaLocation")
|
||||||
|
}
|
||||||
|
x.XSD, err = xsd.Parse(xsdRaw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapNS (tries to) extract the default namespace from the document via the SchemaLocation property of XML, sets DefaultNS,
|
||||||
|
// and then gets the XSDPath specified therein.
|
||||||
|
func (x *NsXml) mapNS() error {
|
||||||
|
if x.XSD.Pointer() != 0 {
|
||||||
|
// Already set.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := x.parse(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
x.DefaultNS = x.Root.NamespaceURI()
|
||||||
|
/* x.DefaultNS = *x.XML.XMLName.Space
|
||||||
|
sl := *x.XML.SchemaLocation
|
||||||
|
*/
|
||||||
|
ns := strings.Fields(sl)
|
||||||
|
if ns != nil {
|
||||||
|
if len(ns) > 2 {
|
||||||
|
return errors.New("too many values for a valid schemaLocation")
|
||||||
|
} else if len(ns) == 0 {
|
||||||
|
return errors.New("no specified value for schemaLocation")
|
||||||
|
} else if len(ns) == 1 {
|
||||||
|
// LAZY. This is improper XML, but is commonly used regardless.
|
||||||
|
x.XSDPath = ns[0]
|
||||||
|
} else {
|
||||||
|
if ns[0] == x.DefaultNS {
|
||||||
|
x.XSDPath = ns[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse parses the x.XML into its x.LXML
|
||||||
|
func (x *NsXml) parse() error {
|
||||||
|
if x.LXML != nil {
|
||||||
|
return nil // Already parsed
|
||||||
|
}
|
||||||
|
if x.XML == nil {
|
||||||
|
return errors.New("XML property is empty")
|
||||||
|
}
|
||||||
|
x.LXML, err = lxml.Parse(*x.XML, lxmlp.XMLParseBigLines, lxmlp.XMLParseXInclude)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
de, err := x.LXML.DocumentElement()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
x.Root = de.(lxmlt.Element)
|
||||||
|
return nil
|
||||||
|
}
|
134
schema.go
134
schema.go
@ -1,131 +1,17 @@
|
|||||||
package conf
|
package main
|
||||||
|
|
||||||
// The usage of this depends on the successful resolution of https://github.com/lestrrat-go/libxml2/issues/67.
|
// The usage of this depends on the successful resolution of https://github.com/lestrrat-go/libxml2/issues/67.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
`errors`
|
"errors"
|
||||||
`io/ioutil`
|
"io/ioutil"
|
||||||
`net/http`
|
"net/http"
|
||||||
`regexp`
|
"strings"
|
||||||
`strings`
|
|
||||||
|
|
||||||
lxml `github.com/lestrrat-go/libxml2`
|
lxml "github.com/lestrrat-go/libxml2"
|
||||||
lxmlp `github.com/lestrrat-go/libxml2/parser`
|
lxmlp "github.com/lestrrat-go/libxml2/parser"
|
||||||
lxmlt `github.com/lestrrat-go/libxml2/types`
|
lxmlt "github.com/lestrrat-go/libxml2/types"
|
||||||
`github.com/lestrrat-go/libxml2/xsd`
|
"github.com/lestrrat-go/libxml2/xsd"
|
||||||
|
|
||||||
rpaths `r00t2.io/sysutils/paths`
|
rpaths "r00t2.io/sysutils/paths"
|
||||||
)
|
)
|
||||||
|
|
||||||
var uriRe = regexp.MustCompile(`^(?P<type>file|https?)://(?P<path>.+)$`)
|
|
||||||
|
|
||||||
type NSXML struct {
|
|
||||||
XML *[]byte // The raw XML bytes.
|
|
||||||
LXML lxmlt.Document // The lxml.Parse()'d XML.
|
|
||||||
Root lxmlt.Element // The Document's root element
|
|
||||||
XSD xsd.Schema // Its schema.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NSXML) Validate(defaults bool) (bool, error) {
|
|
||||||
// We need the XSD before we can validate.
|
|
||||||
if err := x.getXSD(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NSXML) getXSD() error {
|
|
||||||
if err := x.mapNS(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r := uriRe.FindStringSubmatch(strings.ToLower(x.XSDPath))
|
|
||||||
reResults := make(map[string]string)
|
|
||||||
for i, name := range uriRe.SubexpNames() {
|
|
||||||
if i != 0 && name != "" {
|
|
||||||
reResults[name] = r[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var xsdRaw []byte
|
|
||||||
switch reResults["type"] {
|
|
||||||
case "file":
|
|
||||||
p := reResults["path"]
|
|
||||||
exists, err := rpaths.RealPathExists(&p)
|
|
||||||
if (err != nil) || (!exists) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
xsdRaw, err = ioutil.ReadFile(p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "http", "https":
|
|
||||||
resp, err := http.Get(x.XSDPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
xsdRaw, err = ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("invalid URI type for schemaLocation")
|
|
||||||
}
|
|
||||||
x.XSD, err = xsd.Parse(xsdRaw)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapNS (tries to) extract the default namespace from the document via the SchemaLocation property of XML, sets DefaultNS,
|
|
||||||
// and then gets the XSDPath specified therein.
|
|
||||||
func (x *NSXML) mapNS() error {
|
|
||||||
if x.XSD.Pointer() != 0 {
|
|
||||||
// Already set.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := x.parse(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
x.DefaultNS = x.Root.NamespaceURI()
|
|
||||||
/* x.DefaultNS = *x.XML.XMLName.Space
|
|
||||||
sl := *x.XML.SchemaLocation
|
|
||||||
*/
|
|
||||||
ns := strings.Fields(sl)
|
|
||||||
if ns != nil {
|
|
||||||
if len(ns) > 2 {
|
|
||||||
return errors.New("too many values for a valid schemaLocation")
|
|
||||||
} else if len(ns) == 0 {
|
|
||||||
return errors.New("no specified value for schemaLocation")
|
|
||||||
} else if len(ns) == 1 {
|
|
||||||
// LAZY. This is improper XML, but is commonly used regardless.
|
|
||||||
x.XSDPath = ns[0]
|
|
||||||
} else {
|
|
||||||
if ns[0] == x.DefaultNS {
|
|
||||||
x.XSDPath = ns[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse parses the x.XML into its x.LXML
|
|
||||||
func (x *NSXML) parse() error {
|
|
||||||
if x.LXML != nil {
|
|
||||||
return nil // Already parsed
|
|
||||||
}
|
|
||||||
if x.XML == nil {
|
|
||||||
return errors.New("XML property is empty")
|
|
||||||
}
|
|
||||||
x.LXML, err = lxml.Parse(*x.XML, lxmlp.XMLParseBigLines, lxmlp.XMLParseXInclude)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
de, err := x.LXML.DocumentElement()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
x.Root = de.(lxmlt.Element)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
28
types.go
Normal file
28
types.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
lxmlt "github.com/lestrrat-go/libxml2/types"
|
||||||
|
"github.com/lestrrat-go/libxml2/xsd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NsXml is a namespaced XML document.
|
||||||
|
type NsXml struct {
|
||||||
|
// Raw is the raw bytes of the document.
|
||||||
|
Raw *[]byte
|
||||||
|
// XML is the libxml2-parsed document.
|
||||||
|
XML lxmlt.Document
|
||||||
|
// Root is LXML's root element.
|
||||||
|
Root lxmlt.Element
|
||||||
|
// XSD is LXML's schema (NsXsd).
|
||||||
|
XSD *NsXsd
|
||||||
|
}
|
||||||
|
|
||||||
|
// NsXsd is a namespaced XSD (XML Schema Definition).
|
||||||
|
type NsXsd struct {
|
||||||
|
// Raw is the raw bytes of the document.
|
||||||
|
Raw *[]byte
|
||||||
|
// XSD is the libxml2-parsed schema.
|
||||||
|
XSD xsd.Schema
|
||||||
|
// XSDPath is the path of the XSD in a fetchable form (the URI of the document, essentially).
|
||||||
|
XSDPath string
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user