checking in some various work
This commit is contained in:
parent
4bf86f76be
commit
60ed522bc8
31
conf.go
Normal file
31
conf.go
Normal file
@ -0,0 +1,31 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
`fmt`
|
||||
"io/ioutil"
|
||||
|
||||
`github.com/pkg/errors`
|
||||
|
||||
"git.square-r00t.net/go_sysutils.git/paths"
|
||||
)
|
||||
|
||||
// ParseConf parses the path of the XML config provided at confPath ptr by using the confStruct struct ptr.
|
||||
// If an XSD is found in the struct, it will be validated against (returning pass/fail as bool), otherwise always return true unless error.
|
||||
func ParseConf(confPath *string, confStruct *struct{}) (bool, error) {
|
||||
exists, err := paths.RealPathExists(confPath)
|
||||
if !exists {
|
||||
return false, errors.New(fmt.Sprintf("Configuration path %v does not exist", *confPath))
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
xmlDoc, err := ioutil.ReadFile(*confPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = xml.Unmarshal(xmlDoc, confStruct)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
}
|
6
const.go
Normal file
6
const.go
Normal file
@ -0,0 +1,6 @@
|
||||
package conf
|
||||
|
||||
const (
|
||||
XSIVal = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
DefSchemaNS = "xsi"
|
||||
)
|
131
schema.go
Normal file
131
schema.go
Normal file
@ -0,0 +1,131 @@
|
||||
package conf
|
||||
|
||||
// The usage of this depends on the successful resolution of https://github.com/lestrrat-go/libxml2/issues/67.
|
||||
|
||||
import (
|
||||
`errors`
|
||||
`io/ioutil`
|
||||
`net/http`
|
||||
`regexp`
|
||||
`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`
|
||||
)
|
||||
|
||||
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
|
||||
}
|
Loading…
Reference in New Issue
Block a user