[#3896bk] Support parsing XML files
This commit is contained in:
parent
6e9606bc89
commit
1be21b7078
1
go.mod
1
go.mod
|
@ -8,6 +8,7 @@ require (
|
||||||
github.com/Microsoft/go-winio v0.4.7 // indirect
|
github.com/Microsoft/go-winio v0.4.7 // indirect
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
|
||||||
|
github.com/beevik/etree v1.1.0
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23
|
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect
|
||||||
github.com/creasty/defaults v1.3.0
|
github.com/creasty/defaults v1.3.0
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -8,6 +8,8 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
|
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||||
|
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
|
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4=
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4=
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/beevik/etree"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
|
@ -106,16 +107,98 @@ func (f *ConfigurationFile) Parse(path string) error {
|
||||||
case Ini:
|
case Ini:
|
||||||
err = f.parseIniFile(path)
|
err = f.parseIniFile(path)
|
||||||
break
|
break
|
||||||
|
case Xml:
|
||||||
|
err = f.parseXmlFile(path)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parses an xml file.
|
||||||
|
func (f *ConfigurationFile) parseXmlFile(path string) error {
|
||||||
|
doc := etree.NewDocument()
|
||||||
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if _, err := doc.ReadFrom(file); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no root we should create a basic start to the file. This isn't required though,
|
||||||
|
// and if it doesn't work correctly I'll just remove the code.
|
||||||
|
if doc.Root() == nil {
|
||||||
|
doc.CreateProcInst("xml", `version="1.0" encoding="utf-8"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, replacement := range f.Replace {
|
||||||
|
value, _, err := f.LookupConfigurationValue(replacement)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the first item and there is no root element, create that root now and apply
|
||||||
|
// it for future use.
|
||||||
|
if i == 0 && doc.Root() == nil {
|
||||||
|
parts := strings.SplitN(replacement.Match, ".", 2)
|
||||||
|
doc.SetRoot(doc.CreateElement(parts[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
path := "./" + strings.Replace(replacement.Match, ".", "/", -1)
|
||||||
|
|
||||||
|
// If we're not doing a wildcard replacement go ahead and create the
|
||||||
|
// missing element if we cannot find it yet.
|
||||||
|
if !strings.Contains(path, "*") {
|
||||||
|
parts := strings.Split(replacement.Match, ".")
|
||||||
|
|
||||||
|
// Set the initial element to be the root element, and then work from there.
|
||||||
|
var element = doc.Root()
|
||||||
|
|
||||||
|
// Iterate over the path to create the required structure for the given element's path.
|
||||||
|
// This does not set a value, only ensures that the base structure exists. We start at index
|
||||||
|
// 1 because an XML document can only contain a single root element, and from there we'll
|
||||||
|
// work our way down the chain.
|
||||||
|
for _, tag := range parts[1:] {
|
||||||
|
if e := element.FindElement(tag); e == nil {
|
||||||
|
element = element.CreateElement(tag)
|
||||||
|
} else {
|
||||||
|
element = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over the elements we found and update their values.
|
||||||
|
for _, element := range doc.FindElements(path) {
|
||||||
|
element.SetText(string(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you don't truncate the file you'll end up duplicating the data in there (or just appending
|
||||||
|
// to the end of the file. We don't want to do that.
|
||||||
|
if err := file.Truncate(0); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the cursor to the start of the file to avoid weird spacing issues.
|
||||||
|
file.Seek(0, 0)
|
||||||
|
|
||||||
|
// Ensure the XML is indented properly.
|
||||||
|
doc.Indent(2)
|
||||||
|
|
||||||
|
// Write the XML to the file.
|
||||||
|
_, err = doc.WriteTo(file)
|
||||||
|
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Parses an ini file.
|
// Parses an ini file.
|
||||||
func (f *ConfigurationFile) parseIniFile(path string) error {
|
func (f *ConfigurationFile) parseIniFile(path string) error {
|
||||||
// Ini package can't handle a non-existent file, so handle that automatically here
|
// Ini package can't handle a non-existent file, so handle that automatically here
|
||||||
// by creating it if not exists.
|
// by creating it if not exists.
|
||||||
file, err := os.OpenFile(path, os.O_CREATE | os.O_RDWR, 0644);
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user