Skip to content

Commit 08f46d7

Browse files
committed
Fix #67: Support basic XPath functions
1 parent d95f6b6 commit 08f46d7

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

internal/utils/utils.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"github.com/PuerkitoBio/goquery"
99
"github.com/antchfx/xmlquery"
10+
"github.com/antchfx/xpath"
1011
"github.com/fatih/color"
1112
"golang.org/x/net/html"
1213
"golang.org/x/text/encoding/ianaindex"
@@ -214,13 +215,37 @@ func XPathQuery(reader io.Reader, writer io.Writer, query string, singleNode boo
214215
if n := xmlquery.FindOne(doc, query); n != nil {
215216
return printNodeContent(writer, n, options)
216217
}
217-
} else {
218+
} else if options.WithTags {
218219
for _, n := range xmlquery.Find(doc, query) {
219220
err := printNodeContent(writer, n, options)
220221
if err != nil {
221222
return err
222223
}
223224
}
225+
} else {
226+
expr, _ := xpath.Compile(query)
227+
val := expr.Evaluate(xmlquery.CreateXPathNavigator(doc))
228+
229+
switch typedVal := val.(type) {
230+
case float64:
231+
_, err = fmt.Fprintf(writer, "%.0f\n", typedVal)
232+
case string:
233+
_, err = fmt.Fprintf(writer, "%s\n", strings.TrimSpace(typedVal))
234+
case *xpath.NodeIterator:
235+
for typedVal.MoveNext() {
236+
typedVal.Current()
237+
_, err = fmt.Fprintf(writer, "%s\n", strings.TrimSpace(typedVal.Current().Value()))
238+
if err != nil {
239+
break
240+
}
241+
}
242+
default:
243+
return fmt.Errorf("unknown type error: %v", val)
244+
}
245+
246+
if err != nil {
247+
return err
248+
}
224249
}
225250

226251
return nil

internal/utils/utils_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,23 @@ func TestXPathQuery(t *testing.T) {
102102
type test struct {
103103
input string
104104
node bool
105+
single bool
105106
query string
106107
result string
107108
}
108109

109110
tests := []test{
110-
{input: "formatted.xml", node: false, query: "//first_name", result: "John"},
111-
{input: "unformatted8.xml", node: false, query: "//title", result: "Some Title"},
112-
{input: "unformatted8.xml", node: true, query: "//title", result: "<title>Some Title</title>"},
111+
{input: "formatted.xml", node: false, single: true, query: "//first_name", result: "John"},
112+
{input: "unformatted8.xml", node: false, single: true, query: "//title", result: "Some Title"},
113+
{input: "unformatted8.xml", node: true, single: true, query: "//title", result: "<title>Some Title</title>"},
114+
{input: "unformatted8.xml", node: false, single: false, query: "count(//link)", result: "2"},
113115
}
114116

115117
for _, testCase := range tests {
116118
fileReader := getFileReader(path.Join("..", "..", "test", "data", "xml", testCase.input))
117119
output := new(strings.Builder)
118120
options := QueryOptions{WithTags: testCase.node, Indent: " "}
119-
err := XPathQuery(fileReader, output, testCase.query, true, options)
121+
err := XPathQuery(fileReader, output, testCase.query, testCase.single, options)
120122
assert.Nil(t, err)
121123
assert.Equal(t, testCase.result, strings.Trim(output.String(), "\n"))
122124
}

0 commit comments

Comments
 (0)