diff --git a/go.mod b/go.mod
index cd9bb04..7976f1a 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,6 @@ go 1.18
require (
github.com/basgys/goxml2json v1.1.0
- github.com/beevik/etree v1.1.0
github.com/dtapps/gotime v1.0.1
go.mongodb.org/mongo-driver v1.9.0
)
diff --git a/go.sum b/go.sum
index cdee275..874785f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,5 @@
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
-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/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/vendor/github.com/beevik/etree/.travis.yml b/vendor/github.com/beevik/etree/.travis.yml
deleted file mode 100644
index f4cb25d..0000000
--- a/vendor/github.com/beevik/etree/.travis.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-language: go
-sudo: false
-
-go:
- - 1.11.x
- - tip
-
-matrix:
- allow_failures:
- - go: tip
-
-script:
- - go vet ./...
- - go test -v ./...
diff --git a/vendor/github.com/beevik/etree/CONTRIBUTORS b/vendor/github.com/beevik/etree/CONTRIBUTORS
deleted file mode 100644
index 03211a8..0000000
--- a/vendor/github.com/beevik/etree/CONTRIBUTORS
+++ /dev/null
@@ -1,10 +0,0 @@
-Brett Vickers (beevik)
-Felix Geisendörfer (felixge)
-Kamil Kisiel (kisielk)
-Graham King (grahamking)
-Matt Smith (ma314smith)
-Michal Jemala (michaljemala)
-Nicolas Piganeau (npiganeau)
-Chris Brown (ccbrown)
-Earncef Sequeira (earncef)
-Gabriel de Labachelerie (wuzuf)
diff --git a/vendor/github.com/beevik/etree/LICENSE b/vendor/github.com/beevik/etree/LICENSE
deleted file mode 100644
index 26f1f77..0000000
--- a/vendor/github.com/beevik/etree/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright 2015-2019 Brett Vickers. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/beevik/etree/README.md b/vendor/github.com/beevik/etree/README.md
deleted file mode 100644
index 08ec26b..0000000
--- a/vendor/github.com/beevik/etree/README.md
+++ /dev/null
@@ -1,205 +0,0 @@
-[![Build Status](https://travis-ci.org/beevik/etree.svg?branch=master)](https://travis-ci.org/beevik/etree)
-[![GoDoc](https://godoc.org/github.com/beevik/etree?status.svg)](https://godoc.org/github.com/beevik/etree)
-
-etree
-=====
-
-The etree package is a lightweight, pure go package that expresses XML in
-the form of an element tree. Its design was inspired by the Python
-[ElementTree](http://docs.python.org/2/library/xml.etree.elementtree.html)
-module.
-
-Some of the package's capabilities and features:
-
-* Represents XML documents as trees of elements for easy traversal.
-* Imports, serializes, modifies or creates XML documents from scratch.
-* Writes and reads XML to/from files, byte slices, strings and io interfaces.
-* Performs simple or complex searches with lightweight XPath-like query APIs.
-* Auto-indents XML using spaces or tabs for better readability.
-* Implemented in pure go; depends only on standard go libraries.
-* Built on top of the go [encoding/xml](http://golang.org/pkg/encoding/xml)
- package.
-
-### Creating an XML document
-
-The following example creates an XML document from scratch using the etree
-package and outputs its indented contents to stdout.
-```go
-doc := etree.NewDocument()
-doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`)
-doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`)
-
-people := doc.CreateElement("People")
-people.CreateComment("These are all known people")
-
-jon := people.CreateElement("Person")
-jon.CreateAttr("name", "Jon")
-
-sally := people.CreateElement("Person")
-sally.CreateAttr("name", "Sally")
-
-doc.Indent(2)
-doc.WriteTo(os.Stdout)
-```
-
-Output:
-```xml
-
-
-
-
-
-
-
-```
-
-### Reading an XML file
-
-Suppose you have a file on disk called `bookstore.xml` containing the
-following data:
-
-```xml
-
-
-
- Everyday Italian
- Giada De Laurentiis
- 2005
- 30.00
-
-
-
- Harry Potter
- J K. Rowling
- 2005
- 29.99
-
-
-
- XQuery Kick Start
- James McGovern
- Per Bothner
- Kurt Cagle
- James Linn
- Vaidyanathan Nagarajan
- 2003
- 49.99
-
-
-
- Learning XML
- Erik T. Ray
- 2003
- 39.95
-
-
-
-```
-
-This code reads the file's contents into an etree document.
-```go
-doc := etree.NewDocument()
-if err := doc.ReadFromFile("bookstore.xml"); err != nil {
- panic(err)
-}
-```
-
-You can also read XML from a string, a byte slice, or an `io.Reader`.
-
-### Processing elements and attributes
-
-This example illustrates several ways to access elements and attributes using
-etree selection queries.
-```go
-root := doc.SelectElement("bookstore")
-fmt.Println("ROOT element:", root.Tag)
-
-for _, book := range root.SelectElements("book") {
- fmt.Println("CHILD element:", book.Tag)
- if title := book.SelectElement("title"); title != nil {
- lang := title.SelectAttrValue("lang", "unknown")
- fmt.Printf(" TITLE: %s (%s)\n", title.Text(), lang)
- }
- for _, attr := range book.Attr {
- fmt.Printf(" ATTR: %s=%s\n", attr.Key, attr.Value)
- }
-}
-```
-Output:
-```
-ROOT element: bookstore
-CHILD element: book
- TITLE: Everyday Italian (en)
- ATTR: category=COOKING
-CHILD element: book
- TITLE: Harry Potter (en)
- ATTR: category=CHILDREN
-CHILD element: book
- TITLE: XQuery Kick Start (en)
- ATTR: category=WEB
-CHILD element: book
- TITLE: Learning XML (en)
- ATTR: category=WEB
-```
-
-### Path queries
-
-This example uses etree's path functions to select all book titles that fall
-into the category of 'WEB'. The double-slash prefix in the path causes the
-search for book elements to occur recursively; book elements may appear at any
-level of the XML hierarchy.
-```go
-for _, t := range doc.FindElements("//book[@category='WEB']/title") {
- fmt.Println("Title:", t.Text())
-}
-```
-
-Output:
-```
-Title: XQuery Kick Start
-Title: Learning XML
-```
-
-This example finds the first book element under the root bookstore element and
-outputs the tag and text of each of its child elements.
-```go
-for _, e := range doc.FindElements("./bookstore/book[1]/*") {
- fmt.Printf("%s: %s\n", e.Tag, e.Text())
-}
-```
-
-Output:
-```
-title: Everyday Italian
-author: Giada De Laurentiis
-year: 2005
-price: 30.00
-```
-
-This example finds all books with a price of 49.99 and outputs their titles.
-```go
-path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title")
-for _, e := range doc.FindElementsPath(path) {
- fmt.Println(e.Text())
-}
-```
-
-Output:
-```
-XQuery Kick Start
-```
-
-Note that this example uses the FindElementsPath function, which takes as an
-argument a pre-compiled path object. Use precompiled paths when you plan to
-search with the same path more than once.
-
-### Other features
-
-These are just a few examples of the things the etree package can do. See the
-[documentation](http://godoc.org/github.com/beevik/etree) for a complete
-description of its capabilities.
-
-### Contributing
-
-This project accepts contributions. Just fork the repo and submit a pull
-request!
diff --git a/vendor/github.com/beevik/etree/RELEASE_NOTES.md b/vendor/github.com/beevik/etree/RELEASE_NOTES.md
deleted file mode 100644
index ee59d7a..0000000
--- a/vendor/github.com/beevik/etree/RELEASE_NOTES.md
+++ /dev/null
@@ -1,109 +0,0 @@
-Release v1.1.0
-==============
-
-**New Features**
-
-* New attribute helpers.
- * Added the `Element.SortAttrs` method, which lexicographically sorts an
- element's attributes by key.
-* New `ReadSettings` properties.
- * Added `Entity` for the support of custom entity maps.
-* New `WriteSettings` properties.
- * Added `UseCRLF` to allow the output of CR-LF newlines instead of the
- default LF newlines. This is useful on Windows systems.
-* Additional support for text and CDATA sections.
- * The `Element.Text` method now returns the concatenation of all consecutive
- character data tokens immediately following an element's opening tag.
- * Added `Element.SetCData` to replace the character data immediately
- following an element's opening tag with a CDATA section.
- * Added `Element.CreateCData` to create and add a CDATA section child
- `CharData` token to an element.
- * Added `Element.CreateText` to create and add a child text `CharData` token
- to an element.
- * Added `NewCData` to create a parentless CDATA section `CharData` token.
- * Added `NewText` to create a parentless text `CharData`
- token.
- * Added `CharData.IsCData` to detect if the token contains a CDATA section.
- * Added `CharData.IsWhitespace` to detect if the token contains whitespace
- inserted by one of the document Indent functions.
- * Modified `Element.SetText` so that it replaces a run of consecutive
- character data tokens following the element's opening tag (instead of just
- the first one).
-* New "tail text" support.
- * Added the `Element.Tail` method, which returns the text immediately
- following an element's closing tag.
- * Added the `Element.SetTail` method, which modifies the text immediately
- following an element's closing tag.
-* New element child insertion and removal methods.
- * Added the `Element.InsertChildAt` method, which inserts a new child token
- before the specified child token index.
- * Added the `Element.RemoveChildAt` method, which removes the child token at
- the specified child token index.
-* New element and attribute queries.
- * Added the `Element.Index` method, which returns the element's index within
- its parent element's child token list.
- * Added the `Element.NamespaceURI` method to return the namespace URI
- associated with an element.
- * Added the `Attr.NamespaceURI` method to return the namespace URI
- associated with an element.
- * Added the `Attr.Element` method to return the element that an attribute
- belongs to.
-* New Path filter functions.
- * Added `[local-name()='val']` to keep elements whose unprefixed tag matches
- the desired value.
- * Added `[name()='val']` to keep elements whose full tag matches the desired
- value.
- * Added `[namespace-prefix()='val']` to keep elements whose namespace prefix
- matches the desired value.
- * Added `[namespace-uri()='val']` to keep elements whose namespace URI
- matches the desired value.
-
-**Bug Fixes**
-
-* A default XML `CharSetReader` is now used to prevent failed parsing of XML
- documents using certain encodings.
- ([Issue](https://github.com/beevik/etree/issues/53)).
-* All characters are now properly escaped according to XML parsing rules.
- ([Issue](https://github.com/beevik/etree/issues/55)).
-* The `Document.Indent` and `Document.IndentTabs` functions no longer insert
- empty string `CharData` tokens.
-
-**Deprecated**
-
-* `Element`
- * The `InsertChild` method is deprecated. Use `InsertChildAt` instead.
- * The `CreateCharData` method is deprecated. Use `CreateText` instead.
-* `CharData`
- * The `NewCharData` method is deprecated. Use `NewText` instead.
-
-
-Release v1.0.1
-==============
-
-**Changes**
-
-* Added support for absolute etree Path queries. An absolute path begins with
- `/` or `//` and begins its search from the element's document root.
-* Added [`GetPath`](https://godoc.org/github.com/beevik/etree#Element.GetPath)
- and [`GetRelativePath`](https://godoc.org/github.com/beevik/etree#Element.GetRelativePath)
- functions to the [`Element`](https://godoc.org/github.com/beevik/etree#Element)
- type.
-
-**Breaking changes**
-
-* A path starting with `//` is now interpreted as an absolute path.
- Previously, it was interpreted as a relative path starting from the element
- whose
- [`FindElement`](https://godoc.org/github.com/beevik/etree#Element.FindElement)
- method was called. To remain compatible with this release, all paths
- prefixed with `//` should be prefixed with `.//` when called from any
- element other than the document's root.
-* [**edit 2/1/2019**]: Minor releases should not contain breaking changes.
- Even though this breaking change was very minor, it was a mistake to include
- it in this minor release. In the future, all breaking changes will be
- limited to major releases (e.g., version 2.0.0).
-
-Release v1.0.0
-==============
-
-Initial release.
diff --git a/vendor/github.com/beevik/etree/etree.go b/vendor/github.com/beevik/etree/etree.go
deleted file mode 100644
index 9e24f90..0000000
--- a/vendor/github.com/beevik/etree/etree.go
+++ /dev/null
@@ -1,1453 +0,0 @@
-// Copyright 2015-2019 Brett Vickers.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package etree provides XML services through an Element Tree
-// abstraction.
-package etree
-
-import (
- "bufio"
- "bytes"
- "encoding/xml"
- "errors"
- "io"
- "os"
- "sort"
- "strings"
-)
-
-const (
- // NoIndent is used with Indent to disable all indenting.
- NoIndent = -1
-)
-
-// ErrXML is returned when XML parsing fails due to incorrect formatting.
-var ErrXML = errors.New("etree: invalid XML format")
-
-// ReadSettings allow for changing the default behavior of the ReadFrom*
-// methods.
-type ReadSettings struct {
- // CharsetReader to be passed to standard xml.Decoder. Default: nil.
- CharsetReader func(charset string, input io.Reader) (io.Reader, error)
-
- // Permissive allows input containing common mistakes such as missing tags
- // or attribute values. Default: false.
- Permissive bool
-
- // Entity to be passed to standard xml.Decoder. Default: nil.
- Entity map[string]string
-}
-
-// newReadSettings creates a default ReadSettings record.
-func newReadSettings() ReadSettings {
- return ReadSettings{
- CharsetReader: func(label string, input io.Reader) (io.Reader, error) {
- return input, nil
- },
- Permissive: false,
- }
-}
-
-// WriteSettings allow for changing the serialization behavior of the WriteTo*
-// methods.
-type WriteSettings struct {
- // CanonicalEndTags forces the production of XML end tags, even for
- // elements that have no child elements. Default: false.
- CanonicalEndTags bool
-
- // CanonicalText forces the production of XML character references for
- // text data characters &, <, and >. If false, XML character references
- // are also produced for " and '. Default: false.
- CanonicalText bool
-
- // CanonicalAttrVal forces the production of XML character references for
- // attribute value characters &, < and ". If false, XML character
- // references are also produced for > and '. Default: false.
- CanonicalAttrVal bool
-
- // When outputting indented XML, use a carriage return and linefeed
- // ("\r\n") as a new-line delimiter instead of just a linefeed ("\n").
- // This is useful on Windows-based systems.
- UseCRLF bool
-}
-
-// newWriteSettings creates a default WriteSettings record.
-func newWriteSettings() WriteSettings {
- return WriteSettings{
- CanonicalEndTags: false,
- CanonicalText: false,
- CanonicalAttrVal: false,
- UseCRLF: false,
- }
-}
-
-// A Token is an empty interface that represents an Element, CharData,
-// Comment, Directive, or ProcInst.
-type Token interface {
- Parent() *Element
- Index() int
- dup(parent *Element) Token
- setParent(parent *Element)
- setIndex(index int)
- writeTo(w *bufio.Writer, s *WriteSettings)
-}
-
-// A Document is a container holding a complete XML hierarchy. Its embedded
-// element contains zero or more children, one of which is usually the root
-// element. The embedded element may include other children such as
-// processing instructions or BOM CharData tokens.
-type Document struct {
- Element
- ReadSettings ReadSettings
- WriteSettings WriteSettings
-}
-
-// An Element represents an XML element, its attributes, and its child tokens.
-type Element struct {
- Space, Tag string // namespace prefix and tag
- Attr []Attr // key-value attribute pairs
- Child []Token // child tokens (elements, comments, etc.)
- parent *Element // parent element
- index int // token index in parent's children
-}
-
-// An Attr represents a key-value attribute of an XML element.
-type Attr struct {
- Space, Key string // The attribute's namespace prefix and key
- Value string // The attribute value string
- element *Element // element containing the attribute
-}
-
-// charDataFlags are used with CharData tokens to store additional settings.
-type charDataFlags uint8
-
-const (
- // The CharData was created by an indent function as whitespace.
- whitespaceFlag charDataFlags = 1 << iota
-
- // The CharData contains a CDATA section.
- cdataFlag
-)
-
-// CharData can be used to represent character data or a CDATA section within
-// an XML document.
-type CharData struct {
- Data string
- parent *Element
- index int
- flags charDataFlags
-}
-
-// A Comment represents an XML comment.
-type Comment struct {
- Data string
- parent *Element
- index int
-}
-
-// A Directive represents an XML directive.
-type Directive struct {
- Data string
- parent *Element
- index int
-}
-
-// A ProcInst represents an XML processing instruction.
-type ProcInst struct {
- Target string
- Inst string
- parent *Element
- index int
-}
-
-// NewDocument creates an XML document without a root element.
-func NewDocument() *Document {
- return &Document{
- Element{Child: make([]Token, 0)},
- newReadSettings(),
- newWriteSettings(),
- }
-}
-
-// Copy returns a recursive, deep copy of the document.
-func (d *Document) Copy() *Document {
- return &Document{*(d.dup(nil).(*Element)), d.ReadSettings, d.WriteSettings}
-}
-
-// Root returns the root element of the document, or nil if there is no root
-// element.
-func (d *Document) Root() *Element {
- for _, t := range d.Child {
- if c, ok := t.(*Element); ok {
- return c
- }
- }
- return nil
-}
-
-// SetRoot replaces the document's root element with e. If the document
-// already has a root when this function is called, then the document's
-// original root is unbound first. If the element e is bound to another
-// document (or to another element within a document), then it is unbound
-// first.
-func (d *Document) SetRoot(e *Element) {
- if e.parent != nil {
- e.parent.RemoveChild(e)
- }
-
- p := &d.Element
- e.setParent(p)
-
- // If there is already a root element, replace it.
- for i, t := range p.Child {
- if _, ok := t.(*Element); ok {
- t.setParent(nil)
- t.setIndex(-1)
- p.Child[i] = e
- e.setIndex(i)
- return
- }
- }
-
- // No existing root element, so add it.
- p.addChild(e)
-}
-
-// ReadFrom reads XML from the reader r into the document d. It returns the
-// number of bytes read and any error encountered.
-func (d *Document) ReadFrom(r io.Reader) (n int64, err error) {
- return d.Element.readFrom(r, d.ReadSettings)
-}
-
-// ReadFromFile reads XML from the string s into the document d.
-func (d *Document) ReadFromFile(filename string) error {
- f, err := os.Open(filename)
- if err != nil {
- return err
- }
- defer f.Close()
- _, err = d.ReadFrom(f)
- return err
-}
-
-// ReadFromBytes reads XML from the byte slice b into the document d.
-func (d *Document) ReadFromBytes(b []byte) error {
- _, err := d.ReadFrom(bytes.NewReader(b))
- return err
-}
-
-// ReadFromString reads XML from the string s into the document d.
-func (d *Document) ReadFromString(s string) error {
- _, err := d.ReadFrom(strings.NewReader(s))
- return err
-}
-
-// WriteTo serializes an XML document into the writer w. It
-// returns the number of bytes written and any error encountered.
-func (d *Document) WriteTo(w io.Writer) (n int64, err error) {
- cw := newCountWriter(w)
- b := bufio.NewWriter(cw)
- for _, c := range d.Child {
- c.writeTo(b, &d.WriteSettings)
- }
- err, n = b.Flush(), cw.bytes
- return
-}
-
-// WriteToFile serializes an XML document into the file named
-// filename.
-func (d *Document) WriteToFile(filename string) error {
- f, err := os.Create(filename)
- if err != nil {
- return err
- }
- defer f.Close()
- _, err = d.WriteTo(f)
- return err
-}
-
-// WriteToBytes serializes the XML document into a slice of
-// bytes.
-func (d *Document) WriteToBytes() (b []byte, err error) {
- var buf bytes.Buffer
- if _, err = d.WriteTo(&buf); err != nil {
- return
- }
- return buf.Bytes(), nil
-}
-
-// WriteToString serializes the XML document into a string.
-func (d *Document) WriteToString() (s string, err error) {
- var b []byte
- if b, err = d.WriteToBytes(); err != nil {
- return
- }
- return string(b), nil
-}
-
-type indentFunc func(depth int) string
-
-// Indent modifies the document's element tree by inserting character data
-// tokens containing newlines and indentation. The amount of indentation per
-// depth level is given as spaces. Pass etree.NoIndent for spaces if you want
-// no indentation at all.
-func (d *Document) Indent(spaces int) {
- var indent indentFunc
- switch {
- case spaces < 0:
- indent = func(depth int) string { return "" }
- case d.WriteSettings.UseCRLF == true:
- indent = func(depth int) string { return indentCRLF(depth*spaces, indentSpaces) }
- default:
- indent = func(depth int) string { return indentLF(depth*spaces, indentSpaces) }
- }
- d.Element.indent(0, indent)
-}
-
-// IndentTabs modifies the document's element tree by inserting CharData
-// tokens containing newlines and tabs for indentation. One tab is used per
-// indentation level.
-func (d *Document) IndentTabs() {
- var indent indentFunc
- switch d.WriteSettings.UseCRLF {
- case true:
- indent = func(depth int) string { return indentCRLF(depth, indentTabs) }
- default:
- indent = func(depth int) string { return indentLF(depth, indentTabs) }
- }
- d.Element.indent(0, indent)
-}
-
-// NewElement creates an unparented element with the specified tag. The tag
-// may be prefixed by a namespace prefix and a colon.
-func NewElement(tag string) *Element {
- space, stag := spaceDecompose(tag)
- return newElement(space, stag, nil)
-}
-
-// newElement is a helper function that creates an element and binds it to
-// a parent element if possible.
-func newElement(space, tag string, parent *Element) *Element {
- e := &Element{
- Space: space,
- Tag: tag,
- Attr: make([]Attr, 0),
- Child: make([]Token, 0),
- parent: parent,
- index: -1,
- }
- if parent != nil {
- parent.addChild(e)
- }
- return e
-}
-
-// Copy creates a recursive, deep copy of the element and all its attributes
-// and children. The returned element has no parent but can be parented to a
-// another element using AddElement, or to a document using SetRoot.
-func (e *Element) Copy() *Element {
- return e.dup(nil).(*Element)
-}
-
-// FullTag returns the element e's complete tag, including namespace prefix if
-// present.
-func (e *Element) FullTag() string {
- if e.Space == "" {
- return e.Tag
- }
- return e.Space + ":" + e.Tag
-}
-
-// NamespaceURI returns the XML namespace URI associated with the element. If
-// the element is part of the XML default namespace, NamespaceURI returns the
-// empty string.
-func (e *Element) NamespaceURI() string {
- if e.Space == "" {
- return e.findDefaultNamespaceURI()
- }
- return e.findLocalNamespaceURI(e.Space)
-}
-
-// findLocalNamespaceURI finds the namespace URI corresponding to the
-// requested prefix.
-func (e *Element) findLocalNamespaceURI(prefix string) string {
- for _, a := range e.Attr {
- if a.Space == "xmlns" && a.Key == prefix {
- return a.Value
- }
- }
-
- if e.parent == nil {
- return ""
- }
-
- return e.parent.findLocalNamespaceURI(prefix)
-}
-
-// findDefaultNamespaceURI finds the default namespace URI of the element.
-func (e *Element) findDefaultNamespaceURI() string {
- for _, a := range e.Attr {
- if a.Space == "" && a.Key == "xmlns" {
- return a.Value
- }
- }
-
- if e.parent == nil {
- return ""
- }
-
- return e.parent.findDefaultNamespaceURI()
-}
-
-// hasText returns true if the element has character data immediately
-// folllowing the element's opening tag.
-func (e *Element) hasText() bool {
- if len(e.Child) == 0 {
- return false
- }
- _, ok := e.Child[0].(*CharData)
- return ok
-}
-
-// namespacePrefix returns the namespace prefix associated with the element.
-func (e *Element) namespacePrefix() string {
- return e.Space
-}
-
-// name returns the tag associated with the element.
-func (e *Element) name() string {
- return e.Tag
-}
-
-// Text returns all character data immediately following the element's opening
-// tag.
-func (e *Element) Text() string {
- if len(e.Child) == 0 {
- return ""
- }
-
- text := ""
- for _, ch := range e.Child {
- if cd, ok := ch.(*CharData); ok {
- if text == "" {
- text = cd.Data
- } else {
- text = text + cd.Data
- }
- } else {
- break
- }
- }
- return text
-}
-
-// SetText replaces all character data immediately following an element's
-// opening tag with the requested string.
-func (e *Element) SetText(text string) {
- e.replaceText(0, text, 0)
-}
-
-// SetCData replaces all character data immediately following an element's
-// opening tag with a CDATA section.
-func (e *Element) SetCData(text string) {
- e.replaceText(0, text, cdataFlag)
-}
-
-// Tail returns all character data immediately following the element's end
-// tag.
-func (e *Element) Tail() string {
- if e.Parent() == nil {
- return ""
- }
-
- p := e.Parent()
- i := e.Index()
-
- text := ""
- for _, ch := range p.Child[i+1:] {
- if cd, ok := ch.(*CharData); ok {
- if text == "" {
- text = cd.Data
- } else {
- text = text + cd.Data
- }
- } else {
- break
- }
- }
- return text
-}
-
-// SetTail replaces all character data immediately following the element's end
-// tag with the requested string.
-func (e *Element) SetTail(text string) {
- if e.Parent() == nil {
- return
- }
-
- p := e.Parent()
- p.replaceText(e.Index()+1, text, 0)
-}
-
-// replaceText is a helper function that replaces a series of chardata tokens
-// starting at index i with the requested text.
-func (e *Element) replaceText(i int, text string, flags charDataFlags) {
- end := e.findTermCharDataIndex(i)
-
- switch {
- case end == i:
- if text != "" {
- // insert a new chardata token at index i
- cd := newCharData(text, flags, nil)
- e.InsertChildAt(i, cd)
- }
-
- case end == i+1:
- if text == "" {
- // remove the chardata token at index i
- e.RemoveChildAt(i)
- } else {
- // replace the first and only character token at index i
- cd := e.Child[i].(*CharData)
- cd.Data, cd.flags = text, flags
- }
-
- default:
- if text == "" {
- // remove all chardata tokens starting from index i
- copy(e.Child[i:], e.Child[end:])
- removed := end - i
- e.Child = e.Child[:len(e.Child)-removed]
- for j := i; j < len(e.Child); j++ {
- e.Child[j].setIndex(j)
- }
- } else {
- // replace the first chardata token at index i and remove all
- // subsequent chardata tokens
- cd := e.Child[i].(*CharData)
- cd.Data, cd.flags = text, flags
- copy(e.Child[i+1:], e.Child[end:])
- removed := end - (i + 1)
- e.Child = e.Child[:len(e.Child)-removed]
- for j := i + 1; j < len(e.Child); j++ {
- e.Child[j].setIndex(j)
- }
- }
- }
-}
-
-// findTermCharDataIndex finds the index of the first child token that isn't
-// a CharData token. It starts from the requested start index.
-func (e *Element) findTermCharDataIndex(start int) int {
- for i := start; i < len(e.Child); i++ {
- if _, ok := e.Child[i].(*CharData); !ok {
- return i
- }
- }
- return len(e.Child)
-}
-
-// CreateElement creates an element with the specified tag and adds it as the
-// last child element of the element e. The tag may be prefixed by a namespace
-// prefix and a colon.
-func (e *Element) CreateElement(tag string) *Element {
- space, stag := spaceDecompose(tag)
- return newElement(space, stag, e)
-}
-
-// AddChild adds the token t as the last child of element e. If token t was
-// already the child of another element, it is first removed from its current
-// parent element.
-func (e *Element) AddChild(t Token) {
- if t.Parent() != nil {
- t.Parent().RemoveChild(t)
- }
-
- t.setParent(e)
- e.addChild(t)
-}
-
-// InsertChild inserts the token t before e's existing child token ex. If ex
-// is nil or ex is not a child of e, then t is added to the end of e's child
-// token list. If token t was already the child of another element, it is
-// first removed from its current parent element.
-//
-// Deprecated: InsertChild is deprecated. Use InsertChildAt instead.
-func (e *Element) InsertChild(ex Token, t Token) {
- if ex == nil || ex.Parent() != e {
- e.AddChild(t)
- return
- }
-
- if t.Parent() != nil {
- t.Parent().RemoveChild(t)
- }
-
- t.setParent(e)
-
- i := ex.Index()
- e.Child = append(e.Child, nil)
- copy(e.Child[i+1:], e.Child[i:])
- e.Child[i] = t
-
- for j := i; j < len(e.Child); j++ {
- e.Child[j].setIndex(j)
- }
-}
-
-// InsertChildAt inserts the token t into the element e's list of child tokens
-// just before the requested index. If the index is greater than or equal to
-// the length of the list of child tokens, the token t is added to the end of
-// the list.
-func (e *Element) InsertChildAt(index int, t Token) {
- if index >= len(e.Child) {
- e.AddChild(t)
- return
- }
-
- if t.Parent() != nil {
- if t.Parent() == e && t.Index() > index {
- index--
- }
- t.Parent().RemoveChild(t)
- }
-
- t.setParent(e)
-
- e.Child = append(e.Child, nil)
- copy(e.Child[index+1:], e.Child[index:])
- e.Child[index] = t
-
- for j := index; j < len(e.Child); j++ {
- e.Child[j].setIndex(j)
- }
-}
-
-// RemoveChild attempts to remove the token t from element e's list of
-// children. If the token t is a child of e, then it is returned. Otherwise,
-// nil is returned.
-func (e *Element) RemoveChild(t Token) Token {
- if t.Parent() != e {
- return nil
- }
- return e.RemoveChildAt(t.Index())
-}
-
-// RemoveChildAt removes the index-th child token from the element e. The
-// removed child token is returned. If the index is out of bounds, no child is
-// removed and nil is returned.
-func (e *Element) RemoveChildAt(index int) Token {
- if index >= len(e.Child) {
- return nil
- }
-
- t := e.Child[index]
- for j := index + 1; j < len(e.Child); j++ {
- e.Child[j].setIndex(j - 1)
- }
- e.Child = append(e.Child[:index], e.Child[index+1:]...)
- t.setIndex(-1)
- t.setParent(nil)
- return t
-}
-
-// ReadFrom reads XML from the reader r and stores the result as a new child
-// of element e.
-func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err error) {
- r := newCountReader(ri)
- dec := xml.NewDecoder(r)
- dec.CharsetReader = settings.CharsetReader
- dec.Strict = !settings.Permissive
- dec.Entity = settings.Entity
- var stack stack
- stack.push(e)
- for {
- t, err := dec.RawToken()
- switch {
- case err == io.EOF:
- return r.bytes, nil
- case err != nil:
- return r.bytes, err
- case stack.empty():
- return r.bytes, ErrXML
- }
-
- top := stack.peek().(*Element)
-
- switch t := t.(type) {
- case xml.StartElement:
- e := newElement(t.Name.Space, t.Name.Local, top)
- for _, a := range t.Attr {
- e.createAttr(a.Name.Space, a.Name.Local, a.Value, e)
- }
- stack.push(e)
- case xml.EndElement:
- stack.pop()
- case xml.CharData:
- data := string(t)
- var flags charDataFlags
- if isWhitespace(data) {
- flags = whitespaceFlag
- }
- newCharData(data, flags, top)
- case xml.Comment:
- newComment(string(t), top)
- case xml.Directive:
- newDirective(string(t), top)
- case xml.ProcInst:
- newProcInst(t.Target, string(t.Inst), top)
- }
- }
-}
-
-// SelectAttr finds an element attribute matching the requested key and
-// returns it if found. Returns nil if no matching attribute is found. The key
-// may be prefixed by a namespace prefix and a colon.
-func (e *Element) SelectAttr(key string) *Attr {
- space, skey := spaceDecompose(key)
- for i, a := range e.Attr {
- if spaceMatch(space, a.Space) && skey == a.Key {
- return &e.Attr[i]
- }
- }
- return nil
-}
-
-// SelectAttrValue finds an element attribute matching the requested key and
-// returns its value if found. The key may be prefixed by a namespace prefix
-// and a colon. If the key is not found, the dflt value is returned instead.
-func (e *Element) SelectAttrValue(key, dflt string) string {
- space, skey := spaceDecompose(key)
- for _, a := range e.Attr {
- if spaceMatch(space, a.Space) && skey == a.Key {
- return a.Value
- }
- }
- return dflt
-}
-
-// ChildElements returns all elements that are children of element e.
-func (e *Element) ChildElements() []*Element {
- var elements []*Element
- for _, t := range e.Child {
- if c, ok := t.(*Element); ok {
- elements = append(elements, c)
- }
- }
- return elements
-}
-
-// SelectElement returns the first child element with the given tag. The tag
-// may be prefixed by a namespace prefix and a colon. Returns nil if no
-// element with a matching tag was found.
-func (e *Element) SelectElement(tag string) *Element {
- space, stag := spaceDecompose(tag)
- for _, t := range e.Child {
- if c, ok := t.(*Element); ok && spaceMatch(space, c.Space) && stag == c.Tag {
- return c
- }
- }
- return nil
-}
-
-// SelectElements returns a slice of all child elements with the given tag.
-// The tag may be prefixed by a namespace prefix and a colon.
-func (e *Element) SelectElements(tag string) []*Element {
- space, stag := spaceDecompose(tag)
- var elements []*Element
- for _, t := range e.Child {
- if c, ok := t.(*Element); ok && spaceMatch(space, c.Space) && stag == c.Tag {
- elements = append(elements, c)
- }
- }
- return elements
-}
-
-// FindElement returns the first element matched by the XPath-like path
-// string. Returns nil if no element is found using the path. Panics if an
-// invalid path string is supplied.
-func (e *Element) FindElement(path string) *Element {
- return e.FindElementPath(MustCompilePath(path))
-}
-
-// FindElementPath returns the first element matched by the XPath-like path
-// string. Returns nil if no element is found using the path.
-func (e *Element) FindElementPath(path Path) *Element {
- p := newPather()
- elements := p.traverse(e, path)
- switch {
- case len(elements) > 0:
- return elements[0]
- default:
- return nil
- }
-}
-
-// FindElements returns a slice of elements matched by the XPath-like path
-// string. Panics if an invalid path string is supplied.
-func (e *Element) FindElements(path string) []*Element {
- return e.FindElementsPath(MustCompilePath(path))
-}
-
-// FindElementsPath returns a slice of elements matched by the Path object.
-func (e *Element) FindElementsPath(path Path) []*Element {
- p := newPather()
- return p.traverse(e, path)
-}
-
-// GetPath returns the absolute path of the element.
-func (e *Element) GetPath() string {
- path := []string{}
- for seg := e; seg != nil; seg = seg.Parent() {
- if seg.Tag != "" {
- path = append(path, seg.Tag)
- }
- }
-
- // Reverse the path.
- for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 {
- path[i], path[j] = path[j], path[i]
- }
-
- return "/" + strings.Join(path, "/")
-}
-
-// GetRelativePath returns the path of the element relative to the source
-// element. If the two elements are not part of the same element tree, then
-// GetRelativePath returns the empty string.
-func (e *Element) GetRelativePath(source *Element) string {
- var path []*Element
-
- if source == nil {
- return ""
- }
-
- // Build a reverse path from the element toward the root. Stop if the
- // source element is encountered.
- var seg *Element
- for seg = e; seg != nil && seg != source; seg = seg.Parent() {
- path = append(path, seg)
- }
-
- // If we found the source element, reverse the path and compose the
- // string.
- if seg == source {
- if len(path) == 0 {
- return "."
- }
- parts := []string{}
- for i := len(path) - 1; i >= 0; i-- {
- parts = append(parts, path[i].Tag)
- }
- return "./" + strings.Join(parts, "/")
- }
-
- // The source wasn't encountered, so climb from the source element toward
- // the root of the tree until an element in the reversed path is
- // encountered.
-
- findPathIndex := func(e *Element, path []*Element) int {
- for i, ee := range path {
- if e == ee {
- return i
- }
- }
- return -1
- }
-
- climb := 0
- for seg = source; seg != nil; seg = seg.Parent() {
- i := findPathIndex(seg, path)
- if i >= 0 {
- path = path[:i] // truncate at found segment
- break
- }
- climb++
- }
-
- // No element in the reversed path was encountered, so the two elements
- // must not be part of the same tree.
- if seg == nil {
- return ""
- }
-
- // Reverse the (possibly truncated) path and prepend ".." segments to
- // climb.
- parts := []string{}
- for i := 0; i < climb; i++ {
- parts = append(parts, "..")
- }
- for i := len(path) - 1; i >= 0; i-- {
- parts = append(parts, path[i].Tag)
- }
- return strings.Join(parts, "/")
-}
-
-// indent recursively inserts proper indentation between an
-// XML element's child tokens.
-func (e *Element) indent(depth int, indent indentFunc) {
- e.stripIndent()
- n := len(e.Child)
- if n == 0 {
- return
- }
-
- oldChild := e.Child
- e.Child = make([]Token, 0, n*2+1)
- isCharData, firstNonCharData := false, true
- for _, c := range oldChild {
- // Insert NL+indent before child if it's not character data.
- // Exceptions: when it's the first non-character-data child, or when
- // the child is at root depth.
- _, isCharData = c.(*CharData)
- if !isCharData {
- if !firstNonCharData || depth > 0 {
- s := indent(depth)
- if s != "" {
- newCharData(s, whitespaceFlag, e)
- }
- }
- firstNonCharData = false
- }
-
- e.addChild(c)
-
- // Recursively process child elements.
- if ce, ok := c.(*Element); ok {
- ce.indent(depth+1, indent)
- }
- }
-
- // Insert NL+indent before the last child.
- if !isCharData {
- if !firstNonCharData || depth > 0 {
- s := indent(depth - 1)
- if s != "" {
- newCharData(s, whitespaceFlag, e)
- }
- }
- }
-}
-
-// stripIndent removes any previously inserted indentation.
-func (e *Element) stripIndent() {
- // Count the number of non-indent child tokens
- n := len(e.Child)
- for _, c := range e.Child {
- if cd, ok := c.(*CharData); ok && cd.IsWhitespace() {
- n--
- }
- }
- if n == len(e.Child) {
- return
- }
-
- // Strip out indent CharData
- newChild := make([]Token, n)
- j := 0
- for _, c := range e.Child {
- if cd, ok := c.(*CharData); ok && cd.IsWhitespace() {
- continue
- }
- newChild[j] = c
- newChild[j].setIndex(j)
- j++
- }
- e.Child = newChild
-}
-
-// dup duplicates the element.
-func (e *Element) dup(parent *Element) Token {
- ne := &Element{
- Space: e.Space,
- Tag: e.Tag,
- Attr: make([]Attr, len(e.Attr)),
- Child: make([]Token, len(e.Child)),
- parent: parent,
- index: e.index,
- }
- for i, t := range e.Child {
- ne.Child[i] = t.dup(ne)
- }
- for i, a := range e.Attr {
- ne.Attr[i] = a
- }
- return ne
-}
-
-// Parent returns the element token's parent element, or nil if it has no
-// parent.
-func (e *Element) Parent() *Element {
- return e.parent
-}
-
-// Index returns the index of this element within its parent element's
-// list of child tokens. If this element has no parent element, the index
-// is -1.
-func (e *Element) Index() int {
- return e.index
-}
-
-// setParent replaces the element token's parent.
-func (e *Element) setParent(parent *Element) {
- e.parent = parent
-}
-
-// setIndex sets the element token's index within its parent's Child slice.
-func (e *Element) setIndex(index int) {
- e.index = index
-}
-
-// writeTo serializes the element to the writer w.
-func (e *Element) writeTo(w *bufio.Writer, s *WriteSettings) {
- w.WriteByte('<')
- w.WriteString(e.FullTag())
- for _, a := range e.Attr {
- w.WriteByte(' ')
- a.writeTo(w, s)
- }
- if len(e.Child) > 0 {
- w.WriteString(">")
- for _, c := range e.Child {
- c.writeTo(w, s)
- }
- w.Write([]byte{'<', '/'})
- w.WriteString(e.FullTag())
- w.WriteByte('>')
- } else {
- if s.CanonicalEndTags {
- w.Write([]byte{'>', '<', '/'})
- w.WriteString(e.FullTag())
- w.WriteByte('>')
- } else {
- w.Write([]byte{'/', '>'})
- }
- }
-}
-
-// addChild adds a child token to the element e.
-func (e *Element) addChild(t Token) {
- t.setIndex(len(e.Child))
- e.Child = append(e.Child, t)
-}
-
-// CreateAttr creates an attribute and adds it to element e. The key may be
-// prefixed by a namespace prefix and a colon. If an attribute with the key
-// already exists, its value is replaced.
-func (e *Element) CreateAttr(key, value string) *Attr {
- space, skey := spaceDecompose(key)
- return e.createAttr(space, skey, value, e)
-}
-
-// createAttr is a helper function that creates attributes.
-func (e *Element) createAttr(space, key, value string, parent *Element) *Attr {
- for i, a := range e.Attr {
- if space == a.Space && key == a.Key {
- e.Attr[i].Value = value
- return &e.Attr[i]
- }
- }
- a := Attr{
- Space: space,
- Key: key,
- Value: value,
- element: parent,
- }
- e.Attr = append(e.Attr, a)
- return &e.Attr[len(e.Attr)-1]
-}
-
-// RemoveAttr removes and returns a copy of the first attribute of the element
-// whose key matches the given key. The key may be prefixed by a namespace
-// prefix and a colon. If a matching attribute does not exist, nil is
-// returned.
-func (e *Element) RemoveAttr(key string) *Attr {
- space, skey := spaceDecompose(key)
- for i, a := range e.Attr {
- if space == a.Space && skey == a.Key {
- e.Attr = append(e.Attr[0:i], e.Attr[i+1:]...)
- return &Attr{
- Space: a.Space,
- Key: a.Key,
- Value: a.Value,
- element: nil,
- }
- }
- }
- return nil
-}
-
-// SortAttrs sorts the element's attributes lexicographically by key.
-func (e *Element) SortAttrs() {
- sort.Sort(byAttr(e.Attr))
-}
-
-type byAttr []Attr
-
-func (a byAttr) Len() int {
- return len(a)
-}
-
-func (a byAttr) Swap(i, j int) {
- a[i], a[j] = a[j], a[i]
-}
-
-func (a byAttr) Less(i, j int) bool {
- sp := strings.Compare(a[i].Space, a[j].Space)
- if sp == 0 {
- return strings.Compare(a[i].Key, a[j].Key) < 0
- }
- return sp < 0
-}
-
-// FullKey returns the attribute a's complete key, including namespace prefix
-// if present.
-func (a *Attr) FullKey() string {
- if a.Space == "" {
- return a.Key
- }
- return a.Space + ":" + a.Key
-}
-
-// Element returns the element containing the attribute.
-func (a *Attr) Element() *Element {
- return a.element
-}
-
-// NamespaceURI returns the XML namespace URI associated with the attribute.
-// If the element is part of the XML default namespace, NamespaceURI returns
-// the empty string.
-func (a *Attr) NamespaceURI() string {
- return a.element.NamespaceURI()
-}
-
-// writeTo serializes the attribute to the writer.
-func (a *Attr) writeTo(w *bufio.Writer, s *WriteSettings) {
- w.WriteString(a.FullKey())
- w.WriteString(`="`)
- var m escapeMode
- if s.CanonicalAttrVal {
- m = escapeCanonicalAttr
- } else {
- m = escapeNormal
- }
- escapeString(w, a.Value, m)
- w.WriteByte('"')
-}
-
-// NewText creates a parentless CharData token containing character data.
-func NewText(text string) *CharData {
- return newCharData(text, 0, nil)
-}
-
-// NewCData creates a parentless XML character CDATA section.
-func NewCData(data string) *CharData {
- return newCharData(data, cdataFlag, nil)
-}
-
-// NewCharData creates a parentless CharData token containing character data.
-//
-// Deprecated: NewCharData is deprecated. Instead, use NewText, which does the
-// same thing.
-func NewCharData(data string) *CharData {
- return newCharData(data, 0, nil)
-}
-
-// newCharData creates a character data token and binds it to a parent
-// element. If parent is nil, the CharData token remains unbound.
-func newCharData(data string, flags charDataFlags, parent *Element) *CharData {
- c := &CharData{
- Data: data,
- parent: parent,
- index: -1,
- flags: flags,
- }
- if parent != nil {
- parent.addChild(c)
- }
- return c
-}
-
-// CreateText creates a CharData token containing character data and adds it
-// as a child of element e.
-func (e *Element) CreateText(text string) *CharData {
- return newCharData(text, 0, e)
-}
-
-// CreateCData creates a CharData token containing a CDATA section and adds it
-// as a child of element e.
-func (e *Element) CreateCData(data string) *CharData {
- return newCharData(data, cdataFlag, e)
-}
-
-// CreateCharData creates a CharData token containing character data and adds
-// it as a child of element e.
-//
-// Deprecated: CreateCharData is deprecated. Instead, use CreateText, which
-// does the same thing.
-func (e *Element) CreateCharData(data string) *CharData {
- return newCharData(data, 0, e)
-}
-
-// dup duplicates the character data.
-func (c *CharData) dup(parent *Element) Token {
- return &CharData{
- Data: c.Data,
- flags: c.flags,
- parent: parent,
- index: c.index,
- }
-}
-
-// IsCData returns true if the character data token is to be encoded as a
-// CDATA section.
-func (c *CharData) IsCData() bool {
- return (c.flags & cdataFlag) != 0
-}
-
-// IsWhitespace returns true if the character data token was created by one of
-// the document Indent methods to contain only whitespace.
-func (c *CharData) IsWhitespace() bool {
- return (c.flags & whitespaceFlag) != 0
-}
-
-// Parent returns the character data token's parent element, or nil if it has
-// no parent.
-func (c *CharData) Parent() *Element {
- return c.parent
-}
-
-// Index returns the index of this CharData token within its parent element's
-// list of child tokens. If this CharData token has no parent element, the
-// index is -1.
-func (c *CharData) Index() int {
- return c.index
-}
-
-// setParent replaces the character data token's parent.
-func (c *CharData) setParent(parent *Element) {
- c.parent = parent
-}
-
-// setIndex sets the CharData token's index within its parent element's Child
-// slice.
-func (c *CharData) setIndex(index int) {
- c.index = index
-}
-
-// writeTo serializes character data to the writer.
-func (c *CharData) writeTo(w *bufio.Writer, s *WriteSettings) {
- if c.IsCData() {
- w.WriteString(``)
- } else {
- var m escapeMode
- if s.CanonicalText {
- m = escapeCanonicalText
- } else {
- m = escapeNormal
- }
- escapeString(w, c.Data, m)
- }
-}
-
-// NewComment creates a parentless XML comment.
-func NewComment(comment string) *Comment {
- return newComment(comment, nil)
-}
-
-// NewComment creates an XML comment and binds it to a parent element. If
-// parent is nil, the Comment remains unbound.
-func newComment(comment string, parent *Element) *Comment {
- c := &Comment{
- Data: comment,
- parent: parent,
- index: -1,
- }
- if parent != nil {
- parent.addChild(c)
- }
- return c
-}
-
-// CreateComment creates an XML comment and adds it as a child of element e.
-func (e *Element) CreateComment(comment string) *Comment {
- return newComment(comment, e)
-}
-
-// dup duplicates the comment.
-func (c *Comment) dup(parent *Element) Token {
- return &Comment{
- Data: c.Data,
- parent: parent,
- index: c.index,
- }
-}
-
-// Parent returns comment token's parent element, or nil if it has no parent.
-func (c *Comment) Parent() *Element {
- return c.parent
-}
-
-// Index returns the index of this Comment token within its parent element's
-// list of child tokens. If this Comment token has no parent element, the
-// index is -1.
-func (c *Comment) Index() int {
- return c.index
-}
-
-// setParent replaces the comment token's parent.
-func (c *Comment) setParent(parent *Element) {
- c.parent = parent
-}
-
-// setIndex sets the Comment token's index within its parent element's Child
-// slice.
-func (c *Comment) setIndex(index int) {
- c.index = index
-}
-
-// writeTo serialies the comment to the writer.
-func (c *Comment) writeTo(w *bufio.Writer, s *WriteSettings) {
- w.WriteString("")
-}
-
-// NewDirective creates a parentless XML directive.
-func NewDirective(data string) *Directive {
- return newDirective(data, nil)
-}
-
-// newDirective creates an XML directive and binds it to a parent element. If
-// parent is nil, the Directive remains unbound.
-func newDirective(data string, parent *Element) *Directive {
- d := &Directive{
- Data: data,
- parent: parent,
- index: -1,
- }
- if parent != nil {
- parent.addChild(d)
- }
- return d
-}
-
-// CreateDirective creates an XML directive and adds it as the last child of
-// element e.
-func (e *Element) CreateDirective(data string) *Directive {
- return newDirective(data, e)
-}
-
-// dup duplicates the directive.
-func (d *Directive) dup(parent *Element) Token {
- return &Directive{
- Data: d.Data,
- parent: parent,
- index: d.index,
- }
-}
-
-// Parent returns directive token's parent element, or nil if it has no
-// parent.
-func (d *Directive) Parent() *Element {
- return d.parent
-}
-
-// Index returns the index of this Directive token within its parent element's
-// list of child tokens. If this Directive token has no parent element, the
-// index is -1.
-func (d *Directive) Index() int {
- return d.index
-}
-
-// setParent replaces the directive token's parent.
-func (d *Directive) setParent(parent *Element) {
- d.parent = parent
-}
-
-// setIndex sets the Directive token's index within its parent element's Child
-// slice.
-func (d *Directive) setIndex(index int) {
- d.index = index
-}
-
-// writeTo serializes the XML directive to the writer.
-func (d *Directive) writeTo(w *bufio.Writer, s *WriteSettings) {
- w.WriteString("")
-}
-
-// NewProcInst creates a parentless XML processing instruction.
-func NewProcInst(target, inst string) *ProcInst {
- return newProcInst(target, inst, nil)
-}
-
-// newProcInst creates an XML processing instruction and binds it to a parent
-// element. If parent is nil, the ProcInst remains unbound.
-func newProcInst(target, inst string, parent *Element) *ProcInst {
- p := &ProcInst{
- Target: target,
- Inst: inst,
- parent: parent,
- index: -1,
- }
- if parent != nil {
- parent.addChild(p)
- }
- return p
-}
-
-// CreateProcInst creates a processing instruction and adds it as a child of
-// element e.
-func (e *Element) CreateProcInst(target, inst string) *ProcInst {
- return newProcInst(target, inst, e)
-}
-
-// dup duplicates the procinst.
-func (p *ProcInst) dup(parent *Element) Token {
- return &ProcInst{
- Target: p.Target,
- Inst: p.Inst,
- parent: parent,
- index: p.index,
- }
-}
-
-// Parent returns processing instruction token's parent element, or nil if it
-// has no parent.
-func (p *ProcInst) Parent() *Element {
- return p.parent
-}
-
-// Index returns the index of this ProcInst token within its parent element's
-// list of child tokens. If this ProcInst token has no parent element, the
-// index is -1.
-func (p *ProcInst) Index() int {
- return p.index
-}
-
-// setParent replaces the processing instruction token's parent.
-func (p *ProcInst) setParent(parent *Element) {
- p.parent = parent
-}
-
-// setIndex sets the processing instruction token's index within its parent
-// element's Child slice.
-func (p *ProcInst) setIndex(index int) {
- p.index = index
-}
-
-// writeTo serializes the processing instruction to the writer.
-func (p *ProcInst) writeTo(w *bufio.Writer, s *WriteSettings) {
- w.WriteString("")
- w.WriteString(p.Target)
- if p.Inst != "" {
- w.WriteByte(' ')
- w.WriteString(p.Inst)
- }
- w.WriteString("?>")
-}
diff --git a/vendor/github.com/beevik/etree/helpers.go b/vendor/github.com/beevik/etree/helpers.go
deleted file mode 100644
index 825e14e..0000000
--- a/vendor/github.com/beevik/etree/helpers.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2015-2019 Brett Vickers.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package etree
-
-import (
- "bufio"
- "io"
- "strings"
- "unicode/utf8"
-)
-
-// A simple stack
-type stack struct {
- data []interface{}
-}
-
-func (s *stack) empty() bool {
- return len(s.data) == 0
-}
-
-func (s *stack) push(value interface{}) {
- s.data = append(s.data, value)
-}
-
-func (s *stack) pop() interface{} {
- value := s.data[len(s.data)-1]
- s.data[len(s.data)-1] = nil
- s.data = s.data[:len(s.data)-1]
- return value
-}
-
-func (s *stack) peek() interface{} {
- return s.data[len(s.data)-1]
-}
-
-// A fifo is a simple first-in-first-out queue.
-type fifo struct {
- data []interface{}
- head, tail int
-}
-
-func (f *fifo) add(value interface{}) {
- if f.len()+1 >= len(f.data) {
- f.grow()
- }
- f.data[f.tail] = value
- if f.tail++; f.tail == len(f.data) {
- f.tail = 0
- }
-}
-
-func (f *fifo) remove() interface{} {
- value := f.data[f.head]
- f.data[f.head] = nil
- if f.head++; f.head == len(f.data) {
- f.head = 0
- }
- return value
-}
-
-func (f *fifo) len() int {
- if f.tail >= f.head {
- return f.tail - f.head
- }
- return len(f.data) - f.head + f.tail
-}
-
-func (f *fifo) grow() {
- c := len(f.data) * 2
- if c == 0 {
- c = 4
- }
- buf, count := make([]interface{}, c), f.len()
- if f.tail >= f.head {
- copy(buf[0:count], f.data[f.head:f.tail])
- } else {
- hindex := len(f.data) - f.head
- copy(buf[0:hindex], f.data[f.head:])
- copy(buf[hindex:count], f.data[:f.tail])
- }
- f.data, f.head, f.tail = buf, 0, count
-}
-
-// countReader implements a proxy reader that counts the number of
-// bytes read from its encapsulated reader.
-type countReader struct {
- r io.Reader
- bytes int64
-}
-
-func newCountReader(r io.Reader) *countReader {
- return &countReader{r: r}
-}
-
-func (cr *countReader) Read(p []byte) (n int, err error) {
- b, err := cr.r.Read(p)
- cr.bytes += int64(b)
- return b, err
-}
-
-// countWriter implements a proxy writer that counts the number of
-// bytes written by its encapsulated writer.
-type countWriter struct {
- w io.Writer
- bytes int64
-}
-
-func newCountWriter(w io.Writer) *countWriter {
- return &countWriter{w: w}
-}
-
-func (cw *countWriter) Write(p []byte) (n int, err error) {
- b, err := cw.w.Write(p)
- cw.bytes += int64(b)
- return b, err
-}
-
-// isWhitespace returns true if the byte slice contains only
-// whitespace characters.
-func isWhitespace(s string) bool {
- for i := 0; i < len(s); i++ {
- if c := s[i]; c != ' ' && c != '\t' && c != '\n' && c != '\r' {
- return false
- }
- }
- return true
-}
-
-// spaceMatch returns true if namespace a is the empty string
-// or if namespace a equals namespace b.
-func spaceMatch(a, b string) bool {
- switch {
- case a == "":
- return true
- default:
- return a == b
- }
-}
-
-// spaceDecompose breaks a namespace:tag identifier at the ':'
-// and returns the two parts.
-func spaceDecompose(str string) (space, key string) {
- colon := strings.IndexByte(str, ':')
- if colon == -1 {
- return "", str
- }
- return str[:colon], str[colon+1:]
-}
-
-// Strings used by indentCRLF and indentLF
-const (
- indentSpaces = "\r\n "
- indentTabs = "\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
-)
-
-// indentCRLF returns a CRLF newline followed by n copies of the first
-// non-CRLF character in the source string.
-func indentCRLF(n int, source string) string {
- switch {
- case n < 0:
- return source[:2]
- case n < len(source)-1:
- return source[:n+2]
- default:
- return source + strings.Repeat(source[2:3], n-len(source)+2)
- }
-}
-
-// indentLF returns a LF newline followed by n copies of the first non-LF
-// character in the source string.
-func indentLF(n int, source string) string {
- switch {
- case n < 0:
- return source[1:2]
- case n < len(source)-1:
- return source[1 : n+2]
- default:
- return source[1:] + strings.Repeat(source[2:3], n-len(source)+2)
- }
-}
-
-// nextIndex returns the index of the next occurrence of sep in s,
-// starting from offset. It returns -1 if the sep string is not found.
-func nextIndex(s, sep string, offset int) int {
- switch i := strings.Index(s[offset:], sep); i {
- case -1:
- return -1
- default:
- return offset + i
- }
-}
-
-// isInteger returns true if the string s contains an integer.
-func isInteger(s string) bool {
- for i := 0; i < len(s); i++ {
- if (s[i] < '0' || s[i] > '9') && !(i == 0 && s[i] == '-') {
- return false
- }
- }
- return true
-}
-
-type escapeMode byte
-
-const (
- escapeNormal escapeMode = iota
- escapeCanonicalText
- escapeCanonicalAttr
-)
-
-// escapeString writes an escaped version of a string to the writer.
-func escapeString(w *bufio.Writer, s string, m escapeMode) {
- var esc []byte
- last := 0
- for i := 0; i < len(s); {
- r, width := utf8.DecodeRuneInString(s[i:])
- i += width
- switch r {
- case '&':
- esc = []byte("&")
- case '<':
- esc = []byte("<")
- case '>':
- if m == escapeCanonicalAttr {
- continue
- }
- esc = []byte(">")
- case '\'':
- if m != escapeNormal {
- continue
- }
- esc = []byte("'")
- case '"':
- if m == escapeCanonicalText {
- continue
- }
- esc = []byte(""")
- case '\t':
- if m != escapeCanonicalAttr {
- continue
- }
- esc = []byte(" ")
- case '\n':
- if m != escapeCanonicalAttr {
- continue
- }
- esc = []byte("
")
- case '\r':
- if m == escapeNormal {
- continue
- }
- esc = []byte("
")
- default:
- if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
- esc = []byte("\uFFFD")
- break
- }
- continue
- }
- w.WriteString(s[last : i-width])
- w.Write(esc)
- last = i
- }
- w.WriteString(s[last:])
-}
-
-func isInCharacterRange(r rune) bool {
- return r == 0x09 ||
- r == 0x0A ||
- r == 0x0D ||
- r >= 0x20 && r <= 0xD7FF ||
- r >= 0xE000 && r <= 0xFFFD ||
- r >= 0x10000 && r <= 0x10FFFF
-}
diff --git a/vendor/github.com/beevik/etree/path.go b/vendor/github.com/beevik/etree/path.go
deleted file mode 100644
index 82db0ac..0000000
--- a/vendor/github.com/beevik/etree/path.go
+++ /dev/null
@@ -1,582 +0,0 @@
-// Copyright 2015-2019 Brett Vickers.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package etree
-
-import (
- "strconv"
- "strings"
-)
-
-/*
-A Path is a string that represents a search path through an etree starting
-from the document root or an arbitrary element. Paths are used with the
-Element object's Find* methods to locate and return desired elements.
-
-A Path consists of a series of slash-separated "selectors", each of which may
-be modified by one or more bracket-enclosed "filters". Selectors are used to
-traverse the etree from element to element, while filters are used to narrow
-the list of candidate elements at each node.
-
-Although etree Path strings are similar to XPath strings
-(https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more limited set
-of selectors and filtering options.
-
-The following selectors are supported by etree Path strings:
-
- . Select the current element.
- .. Select the parent of the current element.
- * Select all child elements of the current element.
- / Select the root element when used at the start of a path.
- // Select all descendants of the current element.
- tag Select all child elements with a name matching the tag.
-
-The following basic filters are supported by etree Path strings:
-
- [@attrib] Keep elements with an attribute named attrib.
- [@attrib='val'] Keep elements with an attribute named attrib and value matching val.
- [tag] Keep elements with a child element named tag.
- [tag='val'] Keep elements with a child element named tag and text matching val.
- [n] Keep the n-th element, where n is a numeric index starting from 1.
-
-The following function filters are also supported:
-
- [text()] Keep elements with non-empty text.
- [text()='val'] Keep elements whose text matches val.
- [local-name()='val'] Keep elements whose un-prefixed tag matches val.
- [name()='val'] Keep elements whose full tag exactly matches val.
- [namespace-prefix()='val'] Keep elements whose namespace prefix matches val.
- [namespace-uri()='val'] Keep elements whose namespace URI matches val.
-
-Here are some examples of Path strings:
-
-- Select the bookstore child element of the root element:
- /bookstore
-
-- Beginning from the root element, select the title elements of all
-descendant book elements having a 'category' attribute of 'WEB':
- //book[@category='WEB']/title
-
-- Beginning from the current element, select the first descendant
-book element with a title child element containing the text 'Great
-Expectations':
- .//book[title='Great Expectations'][1]
-
-- Beginning from the current element, select all child elements of
-book elements with an attribute 'language' set to 'english':
- ./book/*[@language='english']
-
-- Beginning from the current element, select all child elements of
-book elements containing the text 'special':
- ./book/*[text()='special']
-
-- Beginning from the current element, select all descendant book
-elements whose title child element has a 'language' attribute of 'french':
- .//book/title[@language='french']/..
-
-- Beginning from the current element, select all book elements
-belonging to the http://www.w3.org/TR/html4/ namespace:
- .//book[namespace-uri()='http://www.w3.org/TR/html4/']
-
-*/
-type Path struct {
- segments []segment
-}
-
-// ErrPath is returned by path functions when an invalid etree path is provided.
-type ErrPath string
-
-// Error returns the string describing a path error.
-func (err ErrPath) Error() string {
- return "etree: " + string(err)
-}
-
-// CompilePath creates an optimized version of an XPath-like string that
-// can be used to query elements in an element tree.
-func CompilePath(path string) (Path, error) {
- var comp compiler
- segments := comp.parsePath(path)
- if comp.err != ErrPath("") {
- return Path{nil}, comp.err
- }
- return Path{segments}, nil
-}
-
-// MustCompilePath creates an optimized version of an XPath-like string that
-// can be used to query elements in an element tree. Panics if an error
-// occurs. Use this function to create Paths when you know the path is
-// valid (i.e., if it's hard-coded).
-func MustCompilePath(path string) Path {
- p, err := CompilePath(path)
- if err != nil {
- panic(err)
- }
- return p
-}
-
-// A segment is a portion of a path between "/" characters.
-// It contains one selector and zero or more [filters].
-type segment struct {
- sel selector
- filters []filter
-}
-
-func (seg *segment) apply(e *Element, p *pather) {
- seg.sel.apply(e, p)
- for _, f := range seg.filters {
- f.apply(p)
- }
-}
-
-// A selector selects XML elements for consideration by the
-// path traversal.
-type selector interface {
- apply(e *Element, p *pather)
-}
-
-// A filter pares down a list of candidate XML elements based
-// on a path filter in [brackets].
-type filter interface {
- apply(p *pather)
-}
-
-// A pather is helper object that traverses an element tree using
-// a Path object. It collects and deduplicates all elements matching
-// the path query.
-type pather struct {
- queue fifo
- results []*Element
- inResults map[*Element]bool
- candidates []*Element
- scratch []*Element // used by filters
-}
-
-// A node represents an element and the remaining path segments that
-// should be applied against it by the pather.
-type node struct {
- e *Element
- segments []segment
-}
-
-func newPather() *pather {
- return &pather{
- results: make([]*Element, 0),
- inResults: make(map[*Element]bool),
- candidates: make([]*Element, 0),
- scratch: make([]*Element, 0),
- }
-}
-
-// traverse follows the path from the element e, collecting
-// and then returning all elements that match the path's selectors
-// and filters.
-func (p *pather) traverse(e *Element, path Path) []*Element {
- for p.queue.add(node{e, path.segments}); p.queue.len() > 0; {
- p.eval(p.queue.remove().(node))
- }
- return p.results
-}
-
-// eval evalutes the current path node by applying the remaining
-// path's selector rules against the node's element.
-func (p *pather) eval(n node) {
- p.candidates = p.candidates[0:0]
- seg, remain := n.segments[0], n.segments[1:]
- seg.apply(n.e, p)
-
- if len(remain) == 0 {
- for _, c := range p.candidates {
- if in := p.inResults[c]; !in {
- p.inResults[c] = true
- p.results = append(p.results, c)
- }
- }
- } else {
- for _, c := range p.candidates {
- p.queue.add(node{c, remain})
- }
- }
-}
-
-// A compiler generates a compiled path from a path string.
-type compiler struct {
- err ErrPath
-}
-
-// parsePath parses an XPath-like string describing a path
-// through an element tree and returns a slice of segment
-// descriptors.
-func (c *compiler) parsePath(path string) []segment {
- // If path ends with //, fix it
- if strings.HasSuffix(path, "//") {
- path = path + "*"
- }
-
- var segments []segment
-
- // Check for an absolute path
- if strings.HasPrefix(path, "/") {
- segments = append(segments, segment{new(selectRoot), []filter{}})
- path = path[1:]
- }
-
- // Split path into segments
- for _, s := range splitPath(path) {
- segments = append(segments, c.parseSegment(s))
- if c.err != ErrPath("") {
- break
- }
- }
- return segments
-}
-
-func splitPath(path string) []string {
- pieces := make([]string, 0)
- start := 0
- inquote := false
- for i := 0; i+1 <= len(path); i++ {
- if path[i] == '\'' {
- inquote = !inquote
- } else if path[i] == '/' && !inquote {
- pieces = append(pieces, path[start:i])
- start = i + 1
- }
- }
- return append(pieces, path[start:])
-}
-
-// parseSegment parses a path segment between / characters.
-func (c *compiler) parseSegment(path string) segment {
- pieces := strings.Split(path, "[")
- seg := segment{
- sel: c.parseSelector(pieces[0]),
- filters: []filter{},
- }
- for i := 1; i < len(pieces); i++ {
- fpath := pieces[i]
- if fpath[len(fpath)-1] != ']' {
- c.err = ErrPath("path has invalid filter [brackets].")
- break
- }
- seg.filters = append(seg.filters, c.parseFilter(fpath[:len(fpath)-1]))
- }
- return seg
-}
-
-// parseSelector parses a selector at the start of a path segment.
-func (c *compiler) parseSelector(path string) selector {
- switch path {
- case ".":
- return new(selectSelf)
- case "..":
- return new(selectParent)
- case "*":
- return new(selectChildren)
- case "":
- return new(selectDescendants)
- default:
- return newSelectChildrenByTag(path)
- }
-}
-
-var fnTable = map[string]struct {
- hasFn func(e *Element) bool
- getValFn func(e *Element) string
-}{
- "local-name": {nil, (*Element).name},
- "name": {nil, (*Element).FullTag},
- "namespace-prefix": {nil, (*Element).namespacePrefix},
- "namespace-uri": {nil, (*Element).NamespaceURI},
- "text": {(*Element).hasText, (*Element).Text},
-}
-
-// parseFilter parses a path filter contained within [brackets].
-func (c *compiler) parseFilter(path string) filter {
- if len(path) == 0 {
- c.err = ErrPath("path contains an empty filter expression.")
- return nil
- }
-
- // Filter contains [@attr='val'], [fn()='val'], or [tag='val']?
- eqindex := strings.Index(path, "='")
- if eqindex >= 0 {
- rindex := nextIndex(path, "'", eqindex+2)
- if rindex != len(path)-1 {
- c.err = ErrPath("path has mismatched filter quotes.")
- return nil
- }
-
- key := path[:eqindex]
- value := path[eqindex+2 : rindex]
-
- switch {
- case key[0] == '@':
- return newFilterAttrVal(key[1:], value)
- case strings.HasSuffix(key, "()"):
- fn := key[:len(key)-2]
- if t, ok := fnTable[fn]; ok && t.getValFn != nil {
- return newFilterFuncVal(t.getValFn, value)
- }
- c.err = ErrPath("path has unknown function " + fn)
- return nil
- default:
- return newFilterChildText(key, value)
- }
- }
-
- // Filter contains [@attr], [N], [tag] or [fn()]
- switch {
- case path[0] == '@':
- return newFilterAttr(path[1:])
- case strings.HasSuffix(path, "()"):
- fn := path[:len(path)-2]
- if t, ok := fnTable[fn]; ok && t.hasFn != nil {
- return newFilterFunc(t.hasFn)
- }
- c.err = ErrPath("path has unknown function " + fn)
- return nil
- case isInteger(path):
- pos, _ := strconv.Atoi(path)
- switch {
- case pos > 0:
- return newFilterPos(pos - 1)
- default:
- return newFilterPos(pos)
- }
- default:
- return newFilterChild(path)
- }
-}
-
-// selectSelf selects the current element into the candidate list.
-type selectSelf struct{}
-
-func (s *selectSelf) apply(e *Element, p *pather) {
- p.candidates = append(p.candidates, e)
-}
-
-// selectRoot selects the element's root node.
-type selectRoot struct{}
-
-func (s *selectRoot) apply(e *Element, p *pather) {
- root := e
- for root.parent != nil {
- root = root.parent
- }
- p.candidates = append(p.candidates, root)
-}
-
-// selectParent selects the element's parent into the candidate list.
-type selectParent struct{}
-
-func (s *selectParent) apply(e *Element, p *pather) {
- if e.parent != nil {
- p.candidates = append(p.candidates, e.parent)
- }
-}
-
-// selectChildren selects the element's child elements into the
-// candidate list.
-type selectChildren struct{}
-
-func (s *selectChildren) apply(e *Element, p *pather) {
- for _, c := range e.Child {
- if c, ok := c.(*Element); ok {
- p.candidates = append(p.candidates, c)
- }
- }
-}
-
-// selectDescendants selects all descendant child elements
-// of the element into the candidate list.
-type selectDescendants struct{}
-
-func (s *selectDescendants) apply(e *Element, p *pather) {
- var queue fifo
- for queue.add(e); queue.len() > 0; {
- e := queue.remove().(*Element)
- p.candidates = append(p.candidates, e)
- for _, c := range e.Child {
- if c, ok := c.(*Element); ok {
- queue.add(c)
- }
- }
- }
-}
-
-// selectChildrenByTag selects into the candidate list all child
-// elements of the element having the specified tag.
-type selectChildrenByTag struct {
- space, tag string
-}
-
-func newSelectChildrenByTag(path string) *selectChildrenByTag {
- s, l := spaceDecompose(path)
- return &selectChildrenByTag{s, l}
-}
-
-func (s *selectChildrenByTag) apply(e *Element, p *pather) {
- for _, c := range e.Child {
- if c, ok := c.(*Element); ok && spaceMatch(s.space, c.Space) && s.tag == c.Tag {
- p.candidates = append(p.candidates, c)
- }
- }
-}
-
-// filterPos filters the candidate list, keeping only the
-// candidate at the specified index.
-type filterPos struct {
- index int
-}
-
-func newFilterPos(pos int) *filterPos {
- return &filterPos{pos}
-}
-
-func (f *filterPos) apply(p *pather) {
- if f.index >= 0 {
- if f.index < len(p.candidates) {
- p.scratch = append(p.scratch, p.candidates[f.index])
- }
- } else {
- if -f.index <= len(p.candidates) {
- p.scratch = append(p.scratch, p.candidates[len(p.candidates)+f.index])
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
-
-// filterAttr filters the candidate list for elements having
-// the specified attribute.
-type filterAttr struct {
- space, key string
-}
-
-func newFilterAttr(str string) *filterAttr {
- s, l := spaceDecompose(str)
- return &filterAttr{s, l}
-}
-
-func (f *filterAttr) apply(p *pather) {
- for _, c := range p.candidates {
- for _, a := range c.Attr {
- if spaceMatch(f.space, a.Space) && f.key == a.Key {
- p.scratch = append(p.scratch, c)
- break
- }
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
-
-// filterAttrVal filters the candidate list for elements having
-// the specified attribute with the specified value.
-type filterAttrVal struct {
- space, key, val string
-}
-
-func newFilterAttrVal(str, value string) *filterAttrVal {
- s, l := spaceDecompose(str)
- return &filterAttrVal{s, l, value}
-}
-
-func (f *filterAttrVal) apply(p *pather) {
- for _, c := range p.candidates {
- for _, a := range c.Attr {
- if spaceMatch(f.space, a.Space) && f.key == a.Key && f.val == a.Value {
- p.scratch = append(p.scratch, c)
- break
- }
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
-
-// filterFunc filters the candidate list for elements satisfying a custom
-// boolean function.
-type filterFunc struct {
- fn func(e *Element) bool
-}
-
-func newFilterFunc(fn func(e *Element) bool) *filterFunc {
- return &filterFunc{fn}
-}
-
-func (f *filterFunc) apply(p *pather) {
- for _, c := range p.candidates {
- if f.fn(c) {
- p.scratch = append(p.scratch, c)
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
-
-// filterFuncVal filters the candidate list for elements containing a value
-// matching the result of a custom function.
-type filterFuncVal struct {
- fn func(e *Element) string
- val string
-}
-
-func newFilterFuncVal(fn func(e *Element) string, value string) *filterFuncVal {
- return &filterFuncVal{fn, value}
-}
-
-func (f *filterFuncVal) apply(p *pather) {
- for _, c := range p.candidates {
- if f.fn(c) == f.val {
- p.scratch = append(p.scratch, c)
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
-
-// filterChild filters the candidate list for elements having
-// a child element with the specified tag.
-type filterChild struct {
- space, tag string
-}
-
-func newFilterChild(str string) *filterChild {
- s, l := spaceDecompose(str)
- return &filterChild{s, l}
-}
-
-func (f *filterChild) apply(p *pather) {
- for _, c := range p.candidates {
- for _, cc := range c.Child {
- if cc, ok := cc.(*Element); ok &&
- spaceMatch(f.space, cc.Space) &&
- f.tag == cc.Tag {
- p.scratch = append(p.scratch, c)
- }
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
-
-// filterChildText filters the candidate list for elements having
-// a child element with the specified tag and text.
-type filterChildText struct {
- space, tag, text string
-}
-
-func newFilterChildText(str, text string) *filterChildText {
- s, l := spaceDecompose(str)
- return &filterChildText{s, l, text}
-}
-
-func (f *filterChildText) apply(p *pather) {
- for _, c := range p.candidates {
- for _, cc := range c.Child {
- if cc, ok := cc.(*Element); ok &&
- spaceMatch(f.space, cc.Space) &&
- f.tag == cc.Tag &&
- f.text == cc.Text() {
- p.scratch = append(p.scratch, c)
- }
- }
- }
- p.candidates, p.scratch = p.scratch, p.candidates[0:0]
-}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index be19226..b4483dd 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,9 +1,6 @@
# github.com/basgys/goxml2json v1.1.0
## explicit
github.com/basgys/goxml2json
-# github.com/beevik/etree v1.1.0
-## explicit
-github.com/beevik/etree
# github.com/bitly/go-simplejson v0.5.0
## explicit
# github.com/dtapps/gotime v1.0.1
diff --git a/xml.go b/xml.go
index 88e9471..8e6bbb7 100644
--- a/xml.go
+++ b/xml.go
@@ -1 +1,16 @@
package gomongo
+
+import (
+ "encoding/json"
+ "github.com/basgys/goxml2json"
+ "strings"
+)
+
+// XmlDecodeNoError Xml解码,不报错
+func XmlDecodeNoError(b []byte) map[string]interface{} {
+ xtj := strings.NewReader(string(b))
+ jtx, _ := xml2json.Convert(xtj)
+ var data map[string]interface{}
+ _ = json.Unmarshal(jtx.Bytes(), &data)
+ return data
+}