diff --git a/go.mod b/go.mod
index 90b4df5..7f402a7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,13 +1,13 @@
module git.paulbsd.com/paulbsd/fuelprices
-go 1.19
+go 1.20
require (
- github.com/antchfx/xmlquery v1.3.12
- github.com/antchfx/xpath v1.2.1 // indirect
+ github.com/antchfx/xmlquery v1.3.15
+ github.com/antchfx/xpath v1.2.4 // indirect
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
- golang.org/x/net v0.1.0 // indirect
- golang.org/x/text v0.4.0 // indirect
+ golang.org/x/net v0.8.0 // indirect
+ golang.org/x/text v0.8.0 // indirect
gopkg.in/ini.v1 v1.67.0
)
diff --git a/go.sum b/go.sum
index 3e45245..8fc99f5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,12 @@
github.com/antchfx/xmlquery v1.3.12 h1:6TMGpdjpO/P8VhjnaYPXuqT3qyJ/VsqoyNTmJzNBTQ4=
github.com/antchfx/xmlquery v1.3.12/go.mod h1:3w2RvQvTz+DaT5fSgsELkSJcdNgkmg6vuXDEuhdwsPQ=
+github.com/antchfx/xmlquery v1.3.15 h1:aJConNMi1sMha5G8YJoAIF5P+H+qG1L73bSItWHo8Tw=
+github.com/antchfx/xmlquery v1.3.15/go.mod h1:zMDv5tIGjOxY/JCNNinnle7V/EwthZ5IT8eeCGJKRWA=
github.com/antchfx/xpath v1.2.1 h1:qhp4EW6aCOVr5XIkT+l6LJ9ck/JsUH/yyauNgTQkBF8=
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
+github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
+github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY=
+github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -15,16 +20,43 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
+golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
diff --git a/vendor/github.com/antchfx/xmlquery/README.md b/vendor/github.com/antchfx/xmlquery/README.md
index f9f7a3f..ac65ddc 100644
--- a/vendor/github.com/antchfx/xmlquery/README.md
+++ b/vendor/github.com/antchfx/xmlquery/README.md
@@ -235,6 +235,9 @@ title.FirstChild = title_text
channel.FirstChild = title
fmt.Println(doc.OutputXML(true))
// W3Schools Home Page
+
+fmt.Println(doc.OutputXMLWithOptions(WithOutputSelf()))
+// W3Schools Home Page
```
Questions
diff --git a/vendor/github.com/antchfx/xmlquery/node.go b/vendor/github.com/antchfx/xmlquery/node.go
index 4643695..4c77ed6 100644
--- a/vendor/github.com/antchfx/xmlquery/node.go
+++ b/vendor/github.com/antchfx/xmlquery/node.go
@@ -1,7 +1,6 @@
package xmlquery
import (
- "bytes"
"encoding/xml"
"fmt"
"html"
@@ -50,24 +49,55 @@ type Node struct {
level int // node level in the tree
}
+type outputConfiguration struct {
+ printSelf bool
+ preserveSpaces bool
+ emptyElementTagSupport bool
+ skipComments bool
+}
+
+type OutputOption func(*outputConfiguration)
+
+// WithOutputSelf configures the Node to print the root node itself
+func WithOutputSelf() OutputOption {
+ return func(oc *outputConfiguration) {
+ oc.printSelf = true
+ }
+}
+
+// WithEmptyTagSupport empty tags should be written as and
+// not as
+func WithEmptyTagSupport() OutputOption {
+ return func(oc *outputConfiguration) {
+ oc.emptyElementTagSupport = true
+ }
+}
+
+// WithoutComments will skip comments in output
+func WithoutComments() OutputOption {
+ return func(oc *outputConfiguration) {
+ oc.skipComments = true
+ }
+}
+
// InnerText returns the text between the start and end tags of the object.
func (n *Node) InnerText() string {
- var output func(*bytes.Buffer, *Node)
- output = func(buf *bytes.Buffer, n *Node) {
+ var output func(*strings.Builder, *Node)
+ output = func(b *strings.Builder, n *Node) {
switch n.Type {
case TextNode, CharDataNode:
- buf.WriteString(n.Data)
+ b.WriteString(n.Data)
case CommentNode:
default:
for child := n.FirstChild; child != nil; child = child.NextSibling {
- output(buf, child)
+ output(b, child)
}
}
}
- var buf bytes.Buffer
- output(&buf, n)
- return buf.String()
+ var b strings.Builder
+ output(&b, n)
+ return b.String()
}
func (n *Node) sanitizedData(preserveSpaces bool) string {
@@ -86,72 +116,106 @@ func calculatePreserveSpaces(n *Node, pastValue bool) bool {
return pastValue
}
-func outputXML(buf *bytes.Buffer, n *Node, preserveSpaces bool) {
+func outputXML(b *strings.Builder, n *Node, preserveSpaces bool, config *outputConfiguration) {
preserveSpaces = calculatePreserveSpaces(n, preserveSpaces)
switch n.Type {
case TextNode:
- buf.WriteString(html.EscapeString(n.sanitizedData(preserveSpaces)))
+ b.WriteString(html.EscapeString(n.sanitizedData(preserveSpaces)))
return
case CharDataNode:
- buf.WriteString("")
+ b.WriteString("")
return
case CommentNode:
- buf.WriteString("")
+ if !config.skipComments {
+ b.WriteString("")
+ }
return
case DeclarationNode:
- buf.WriteString("" + n.Data)
+ b.WriteString("" + n.Data)
default:
if n.Prefix == "" {
- buf.WriteString("<" + n.Data)
+ b.WriteString("<" + n.Data)
} else {
- buf.WriteString("<" + n.Prefix + ":" + n.Data)
+ b.WriteString("<" + n.Prefix + ":" + n.Data)
}
}
for _, attr := range n.Attr {
if attr.Name.Space != "" {
- buf.WriteString(fmt.Sprintf(` %s:%s=`, attr.Name.Space, attr.Name.Local))
+ b.WriteString(fmt.Sprintf(` %s:%s=`, attr.Name.Space, attr.Name.Local))
} else {
- buf.WriteString(fmt.Sprintf(` %s=`, attr.Name.Local))
+ b.WriteString(fmt.Sprintf(` %s=`, attr.Name.Local))
}
- buf.WriteByte('"')
- buf.WriteString(html.EscapeString(attr.Value))
- buf.WriteByte('"')
+ b.WriteByte('"')
+ b.WriteString(html.EscapeString(attr.Value))
+ b.WriteByte('"')
}
if n.Type == DeclarationNode {
- buf.WriteString("?>")
+ b.WriteString("?>")
} else {
- buf.WriteString(">")
+ if n.FirstChild != nil || !config.emptyElementTagSupport {
+ b.WriteString(">")
+ } else {
+ b.WriteString("/>")
+ return
+ }
}
for child := n.FirstChild; child != nil; child = child.NextSibling {
- outputXML(buf, child, preserveSpaces)
+ outputXML(b, child, preserveSpaces, config)
}
if n.Type != DeclarationNode {
if n.Prefix == "" {
- buf.WriteString(fmt.Sprintf("%s>", n.Data))
+ b.WriteString(fmt.Sprintf("%s>", n.Data))
} else {
- buf.WriteString(fmt.Sprintf("%s:%s>", n.Prefix, n.Data))
+ b.WriteString(fmt.Sprintf("%s:%s>", n.Prefix, n.Data))
}
}
}
// OutputXML returns the text that including tags name.
func (n *Node) OutputXML(self bool) string {
+
+ config := &outputConfiguration{
+ printSelf: true,
+ emptyElementTagSupport: false,
+ }
preserveSpaces := calculatePreserveSpaces(n, false)
- var buf bytes.Buffer
+ var b strings.Builder
if self && n.Type != DocumentNode {
- outputXML(&buf, n, preserveSpaces)
+ outputXML(&b, n, preserveSpaces, config)
} else {
for n := n.FirstChild; n != nil; n = n.NextSibling {
- outputXML(&buf, n, preserveSpaces)
+ outputXML(&b, n, preserveSpaces, config)
}
}
- return buf.String()
+ return b.String()
+}
+
+// OutputXMLWithOptions returns the text that including tags name.
+func (n *Node) OutputXMLWithOptions(opts ...OutputOption) string {
+
+ config := &outputConfiguration{}
+ // Set the options
+ for _, opt := range opts {
+ opt(config)
+ }
+
+ preserveSpaces := calculatePreserveSpaces(n, false)
+ var b strings.Builder
+ if config.printSelf && n.Type != DocumentNode {
+ outputXML(&b, n, preserveSpaces, config)
+ } else {
+ for n := n.FirstChild; n != nil; n = n.NextSibling {
+ outputXML(&b, n, preserveSpaces, config)
+ }
+ }
+
+ return b.String()
}
// AddAttr adds a new attribute specified by 'key' and 'val' to a node 'n'.
@@ -172,6 +236,55 @@ func AddAttr(n *Node, key, val string) {
n.Attr = append(n.Attr, attr)
}
+// SetAttr allows an attribute value with the specified name to be changed.
+// If the attribute did not previously exist, it will be created.
+func (n *Node) SetAttr(key, value string) {
+ if i := strings.Index(key, ":"); i > 0 {
+ space := key[:i]
+ local := key[i+1:]
+ for idx := 0; idx < len(n.Attr); idx++ {
+ if n.Attr[idx].Name.Space == space && n.Attr[idx].Name.Local == local {
+ n.Attr[idx].Value = value
+ return
+ }
+ }
+
+ AddAttr(n, key, value)
+ } else {
+ for idx := 0; idx < len(n.Attr); idx++ {
+ if n.Attr[idx].Name.Local == key {
+ n.Attr[idx].Value = value
+ return
+ }
+ }
+
+ AddAttr(n, key, value)
+ }
+}
+
+// RemoveAttr removes the attribute with the specified name.
+func (n *Node) RemoveAttr(key string) {
+ removeIdx := -1
+ if i := strings.Index(key, ":"); i > 0 {
+ space := key[:i]
+ local := key[i+1:]
+ for idx := 0; idx < len(n.Attr); idx++ {
+ if n.Attr[idx].Name.Space == space && n.Attr[idx].Name.Local == local {
+ removeIdx = idx
+ }
+ }
+ } else {
+ for idx := 0; idx < len(n.Attr); idx++ {
+ if n.Attr[idx].Name.Local == key {
+ removeIdx = idx
+ }
+ }
+ }
+ if removeIdx != -1 {
+ n.Attr = append(n.Attr[:removeIdx], n.Attr[removeIdx+1:]...)
+ }
+}
+
// AddChild adds a new node 'n' to a node 'parent' as its last child.
func AddChild(parent, n *Node) {
n.Parent = parent
diff --git a/vendor/github.com/antchfx/xmlquery/parse.go b/vendor/github.com/antchfx/xmlquery/parse.go
index 1e8f6a4..ff4bd44 100644
--- a/vendor/github.com/antchfx/xmlquery/parse.go
+++ b/vendor/github.com/antchfx/xmlquery/parse.go
@@ -3,7 +3,6 @@ package xmlquery
import (
"bufio"
"encoding/xml"
- "errors"
"fmt"
"io"
"net/http"
@@ -92,23 +91,35 @@ func (p *parser) parse() (*Node, error) {
case xml.StartElement:
if p.level == 0 {
// mising XML declaration
- node := &Node{Type: DeclarationNode, Data: "xml", level: 1}
+ attributes := make([]Attr, 1)
+ attributes[0].Name = xml.Name{Local: "version"}
+ attributes[0].Value = "1.0"
+ node := &Node{
+ Type: DeclarationNode,
+ Data: "xml",
+ Attr: attributes,
+ level: 1,
+ }
AddChild(p.prev, node)
p.level = 1
p.prev = node
}
// https://www.w3.org/TR/xml-names/#scoping-defaulting
+ var defaultNamespaceURL string
for _, att := range tok.Attr {
if att.Name.Local == "xmlns" {
- p.space2prefix[att.Value] = ""
+ p.space2prefix[att.Value] = "" // reset empty if exist the default namespace
+ defaultNamespaceURL = att.Value
} else if att.Name.Space == "xmlns" {
- p.space2prefix[att.Value] = att.Name.Local
+ if _, ok := p.space2prefix[att.Value]; !ok {
+ p.space2prefix[att.Value] = att.Name.Local
+ }
}
}
- if tok.Name.Space != "" {
- if _, found := p.space2prefix[tok.Name.Space]; !found {
- return nil, errors.New("xmlquery: invalid XML document, namespace is missing")
+ if space := tok.Name.Space; space != "" {
+ if _, found := p.space2prefix[space]; !found && p.decoder.Strict {
+ return nil, fmt.Errorf("xmlquery: invalid XML document, namespace %s is missing", space)
}
}
@@ -128,7 +139,6 @@ func (p *parser) parse() (*Node, error) {
node := &Node{
Type: ElementNode,
Data: tok.Name.Local,
- Prefix: p.space2prefix[tok.Name.Space],
NamespaceURI: tok.Name.Space,
Attr: attributes,
level: p.level,
@@ -144,6 +154,14 @@ func (p *parser) parse() (*Node, error) {
}
AddSibling(p.prev.Parent, node)
}
+ if node.NamespaceURI != "" {
+ node.Prefix = p.space2prefix[node.NamespaceURI]
+ if defaultNamespaceURL != "" && node.NamespaceURI == defaultNamespaceURL {
+ node.Prefix = ""
+ } else if n := node.Parent; n != nil && node.NamespaceURI == n.NamespaceURI {
+ node.Prefix = n.Prefix
+ }
+ }
// If we're in the streaming mode, we need to remember the node if it is the target node
// so that when we finish processing the node's EndElement, we know how/what to return to
// caller. Also we need to remove the target node from the tree upon next Read() call so
diff --git a/vendor/github.com/antchfx/xpath/build.go b/vendor/github.com/antchfx/xpath/build.go
index 10a5440..4129a21 100644
--- a/vendor/github.com/antchfx/xpath/build.go
+++ b/vendor/github.com/antchfx/xpath/build.go
@@ -44,6 +44,12 @@ func axisPredicate(root *axisNode) func(NodeNavigator) bool {
predicate := func(n NodeNavigator) bool {
if typ == n.NodeType() || typ == allNode {
if nametest {
+ type namespaceURL interface {
+ NamespaceURL() string
+ }
+ if ns, ok := n.(namespaceURL); ok && root.hasNamespaceURI {
+ return root.LocalName == n.LocalName() && root.namespaceURI == ns.NamespaceURL()
+ }
if root.LocalName == n.LocalName() && root.Prefix == n.Prefix() {
return true
}
@@ -88,7 +94,10 @@ func (b *builder) processAxisNode(root *axisNode) (query, error) {
}
return v
}
- qyOutput = &descendantQuery{Input: qyGrandInput, Predicate: filter, Self: true}
+ // fix `//*[contains(@id,"food")]//*[contains(@id,"food")]`, see https://github.com/antchfx/htmlquery/issues/52
+ // Skip the current node(Self:false) for the next descendants nodes.
+ _, ok := qyGrandInput.(*contextQuery)
+ qyOutput = &descendantQuery{Input: qyGrandInput, Predicate: filter, Self: ok}
return qyOutput, nil
}
}
@@ -347,7 +356,15 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
},
}
case "last":
- qyOutput = &functionQuery{Input: b.firstInput, Func: lastFunc}
+ switch typ := b.firstInput.(type) {
+ case *groupQuery, *filterQuery:
+ // https://github.com/antchfx/xpath/issues/76
+ // https://github.com/antchfx/xpath/issues/78
+ qyOutput = &lastQuery{Input: typ}
+ default:
+ qyOutput = &functionQuery{Input: b.firstInput, Func: lastFunc}
+ }
+
case "position":
qyOutput = &functionQuery{Input: b.firstInput, Func: positionFunc}
case "boolean", "number", "string":
@@ -511,6 +528,7 @@ func (b *builder) processNode(root node) (q query, err error) {
b.firstInput = q
case nodeFilter:
q, err = b.processFilterNode(root.(*filterNode))
+ b.firstInput = q
case nodeFunction:
q, err = b.processFunctionNode(root.(*functionNode))
case nodeOperator:
@@ -521,12 +539,13 @@ func (b *builder) processNode(root node) (q query, err error) {
return
}
q = &groupQuery{Input: q}
+ b.firstInput = q
}
return
}
// build builds a specified XPath expressions expr.
-func build(expr string) (q query, err error) {
+func build(expr string, namespaces map[string]string) (q query, err error) {
defer func() {
if e := recover(); e != nil {
switch x := e.(type) {
@@ -539,7 +558,7 @@ func build(expr string) (q query, err error) {
}
}
}()
- root := parse(expr)
+ root := parse(expr, namespaces)
b := &builder{}
return b.processNode(root)
}
diff --git a/vendor/github.com/antchfx/xpath/parse.go b/vendor/github.com/antchfx/xpath/parse.go
index acb0db9..cbd289a 100644
--- a/vendor/github.com/antchfx/xpath/parse.go
+++ b/vendor/github.com/antchfx/xpath/parse.go
@@ -69,8 +69,9 @@ const (
)
type parser struct {
- r *scanner
- d int
+ r *scanner
+ d int
+ namespaces map[string]string
}
// newOperatorNode returns new operator node OperatorNode.
@@ -84,8 +85,8 @@ func newOperandNode(v interface{}) node {
}
// newAxisNode returns new axis node AxisNode.
-func newAxisNode(axeTyp, localName, prefix, prop string, n node) node {
- return &axisNode{
+func newAxisNode(axeTyp, localName, prefix, prop string, n node, opts ...func(p *axisNode)) node {
+ a := axisNode{
nodeType: nodeAxis,
LocalName: localName,
Prefix: prefix,
@@ -93,6 +94,10 @@ func newAxisNode(axeTyp, localName, prefix, prop string, n node) node {
Prop: prop,
Input: n,
}
+ for _, o := range opts {
+ o(&a)
+ }
+ return &a
}
// newVariableNode returns new variable node VariableNode.
@@ -469,7 +474,16 @@ func (p *parser) parseNodeTest(n node, axeTyp string) (opnd node) {
if p.r.name == "*" {
name = ""
}
- opnd = newAxisNode(axeTyp, name, prefix, "", n)
+ opnd = newAxisNode(axeTyp, name, prefix, "", n, func(a *axisNode) {
+ if prefix != "" && p.namespaces != nil {
+ if ns, ok := p.namespaces[prefix]; ok {
+ a.hasNamespaceURI = true
+ a.namespaceURI = ns
+ } else {
+ panic(fmt.Sprintf("prefix %s not defined.", prefix))
+ }
+ }
+ })
}
case itemStar:
opnd = newAxisNode(axeTyp, "", "", "", n)
@@ -531,11 +545,11 @@ func (p *parser) parseMethod(n node) node {
}
// Parse parsing the XPath express string expr and returns a tree node.
-func parse(expr string) node {
+func parse(expr string, namespaces map[string]string) node {
r := &scanner{text: expr}
r.nextChar()
r.nextItem()
- p := &parser{r: r}
+ p := &parser{r: r, namespaces: namespaces}
return p.parseExpression(nil)
}
@@ -563,11 +577,13 @@ func (o *operatorNode) String() string {
// axisNode holds a location step.
type axisNode struct {
nodeType
- Input node
- Prop string // node-test name.[comment|text|processing-instruction|node]
- AxeType string // name of the axes.[attribute|ancestor|child|....]
- LocalName string // local part name of node.
- Prefix string // prefix name of node.
+ Input node
+ Prop string // node-test name.[comment|text|processing-instruction|node]
+ AxeType string // name of the axes.[attribute|ancestor|child|....]
+ LocalName string // local part name of node.
+ Prefix string // prefix name of node.
+ namespaceURI string // namespace URI of node
+ hasNamespaceURI bool // if namespace URI is set (can be "")
}
func (a *axisNode) String() string {
diff --git a/vendor/github.com/antchfx/xpath/query.go b/vendor/github.com/antchfx/xpath/query.go
index 6ceb033..4e6c634 100644
--- a/vendor/github.com/antchfx/xpath/query.go
+++ b/vendor/github.com/antchfx/xpath/query.go
@@ -56,7 +56,7 @@ func (c *contextQuery) Evaluate(iterator) interface{} {
}
func (c *contextQuery) Clone() query {
- return &contextQuery{count: 0, Root: c.Root}
+ return &contextQuery{Root: c.Root}
}
// ancestorQuery is an XPath ancestor node query.(ancestor::*|ancestor-self::*)
@@ -558,8 +558,8 @@ func (f *filterQuery) do(t iterator) bool {
pt := getNodePosition(f.Input)
return int(val.Float()) == pt
default:
- if q, ok := f.Predicate.(query); ok {
- return q.Select(t) != nil
+ if f.Predicate != nil {
+ return f.Predicate.Select(t) != nil
}
}
return false
@@ -577,7 +577,7 @@ func (f *filterQuery) Select(t iterator) NodeNavigator {
node := f.Input.Select(t)
if node == nil {
- return node
+ return nil
}
node = node.Copy()
@@ -676,14 +676,12 @@ type groupQuery struct {
}
func (g *groupQuery) Select(t iterator) NodeNavigator {
- for {
- node := g.Input.Select(t)
- if node == nil {
- return nil
- }
- g.posit++
- return node.Copy()
+ node := g.Input.Select(t)
+ if node == nil {
+ return nil
}
+ g.posit++
+ return node
}
func (g *groupQuery) Evaluate(t iterator) interface{} {
@@ -691,7 +689,7 @@ func (g *groupQuery) Evaluate(t iterator) interface{} {
}
func (g *groupQuery) Clone() query {
- return &groupQuery{Input: g.Input}
+ return &groupQuery{Input: g.Input.Clone()}
}
func (g *groupQuery) position() int {
@@ -896,6 +894,35 @@ func (u *unionQuery) Clone() query {
return &unionQuery{Left: u.Left.Clone(), Right: u.Right.Clone()}
}
+type lastQuery struct {
+ buffer []NodeNavigator
+ counted bool
+
+ Input query
+}
+
+func (q *lastQuery) Select(t iterator) NodeNavigator {
+ return nil
+}
+
+func (q *lastQuery) Evaluate(t iterator) interface{} {
+ if !q.counted {
+ for {
+ node := q.Input.Select(t)
+ if node == nil {
+ break
+ }
+ q.buffer = append(q.buffer, node.Copy())
+ }
+ q.counted = true
+ }
+ return float64(len(q.buffer))
+}
+
+func (q *lastQuery) Clone() query {
+ return &lastQuery{Input: q.Input.Clone()}
+}
+
func getHashCode(n NodeNavigator) uint64 {
var sb bytes.Buffer
switch n.NodeType() {
diff --git a/vendor/github.com/antchfx/xpath/xpath.go b/vendor/github.com/antchfx/xpath/xpath.go
index 5f6aa89..1c0a5a2 100644
--- a/vendor/github.com/antchfx/xpath/xpath.go
+++ b/vendor/github.com/antchfx/xpath/xpath.go
@@ -141,7 +141,7 @@ func Compile(expr string) (*Expr, error) {
if expr == "" {
return nil, errors.New("expr expression is nil")
}
- qy, err := build(expr)
+ qy, err := build(expr, nil)
if err != nil {
return nil, err
}
@@ -159,3 +159,18 @@ func MustCompile(expr string) *Expr {
}
return exp
}
+
+// CompileWithNS compiles an XPath expression string, using given namespaces map.
+func CompileWithNS(expr string, namespaces map[string]string) (*Expr, error) {
+ if expr == "" {
+ return nil, errors.New("expr expression is nil")
+ }
+ qy, err := build(expr, namespaces)
+ if err != nil {
+ return nil, err
+ }
+ if qy == nil {
+ return nil, fmt.Errorf(fmt.Sprintf("undeclared variable in XPath expression: %s", expr))
+ }
+ return &Expr{s: expr, q: qy}, nil
+}
diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go
index 822ed42..7a96eae 100644
--- a/vendor/golang.org/x/net/html/doc.go
+++ b/vendor/golang.org/x/net/html/doc.go
@@ -92,6 +92,21 @@ example, to process each anchor node in depth-first order:
The relevant specifications include:
https://html.spec.whatwg.org/multipage/syntax.html and
https://html.spec.whatwg.org/multipage/syntax.html#tokenization
+
+# Security Considerations
+
+Care should be taken when parsing and interpreting HTML, whether full documents
+or fragments, within the framework of the HTML specification, especially with
+regard to untrusted inputs.
+
+This package provides both a tokenizer and a parser. Only the parser constructs
+a DOM according to the HTML specification, resolving malformed and misplaced
+tags where appropriate. The tokenizer simply tokenizes the HTML presented to it,
+and as such does not resolve issues that may exist in the processed HTML,
+producing a literal interpretation of the input.
+
+If your use case requires semantically well-formed HTML, as defined by the
+WHATWG specifiction, the parser should be used rather than the tokenizer.
*/
package html // import "golang.org/x/net/html"
diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go
index d856139..04c6bec 100644
--- a/vendor/golang.org/x/net/html/escape.go
+++ b/vendor/golang.org/x/net/html/escape.go
@@ -193,6 +193,87 @@ func lower(b []byte) []byte {
return b
}
+// escapeComment is like func escape but escapes its input bytes less often.
+// Per https://github.com/golang/go/issues/58246 some HTML comments are (1)
+// meaningful and (2) contain angle brackets that we'd like to avoid escaping
+// unless we have to.
+//
+// "We have to" includes the '&' byte, since that introduces other escapes.
+//
+// It also includes those bytes (not including EOF) that would otherwise end
+// the comment. Per the summary table at the bottom of comment_test.go, this is
+// the '>' byte that, per above, we'd like to avoid escaping unless we have to.
+//
+// Studying the summary table (and T actions in its '>' column) closely, we
+// only need to escape in states 43, 44, 49, 51 and 52. State 43 is at the
+// start of the comment data. State 52 is after a '!'. The other three states
+// are after a '-'.
+//
+// Our algorithm is thus to escape every '&' and to escape '>' if and only if:
+// - The '>' is after a '!' or '-' (in the unescaped data) or
+// - The '>' is at the start of the comment data (after the opening ""); err != nil {
diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go
index be3c754..5c2a1f4 100644
--- a/vendor/golang.org/x/net/html/token.go
+++ b/vendor/golang.org/x/net/html/token.go
@@ -110,7 +110,7 @@ func (t Token) String() string {
case SelfClosingTagToken:
return "<" + t.tagString() + "/>"
case CommentToken:
- return ""
+ return ""
case DoctypeToken:
return ""
}
@@ -598,6 +598,11 @@ scriptDataDoubleEscapeEnd:
// readComment reads the next comment token starting with "")
return
}
@@ -628,19 +632,52 @@ func (z *Tokenizer) readComment() {
if dashCount >= 2 {
c = z.readByte()
if z.err != nil {
- z.data.end = z.raw.end
+ z.data.end = z.calculateAbruptCommentDataEnd()
return
- }
- if c == '>' {
+ } else if c == '>' {
z.data.end = z.raw.end - len("--!>")
return
+ } else if c == '-' {
+ dashCount = 1
+ beginning = false
+ continue
}
}
}
dashCount = 0
+ beginning = false
}
}
+func (z *Tokenizer) calculateAbruptCommentDataEnd() int {
+ raw := z.Raw()
+ const prefixLen = len("