Skip to content

Commit 5bf87b8

Browse files
committed
fix for xpath namespace queries
1 parent 264d57c commit 5bf87b8

File tree

4 files changed

+94
-5
lines changed

4 files changed

+94
-5
lines changed

element.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ type XMLElement struct {
77
Childs map[string][]XMLElement
88
Err error
99
// filled when xpath enabled
10-
childs []*XMLElement
11-
parent *XMLElement
12-
attrs []*xmlAttr
10+
childs []*XMLElement
11+
parent *XMLElement
12+
attrs []*xmlAttr
13+
localName string
14+
prefix string
1315
}
1416

1517
type xmlAttr struct {

query.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,15 @@ func (x *XmlNodeNavigator) LocalName() string {
7878
if x.attr != -1 {
7979
return x.curr.attrs[x.attr].name
8080
}
81-
return x.curr.Name
81+
82+
return x.curr.localName
8283

8384
}
8485

8586
func (x *XmlNodeNavigator) Prefix() string {
86-
return ""
87+
88+
return x.curr.prefix
89+
8790
}
8891

8992
func (x *XmlNodeNavigator) Value() string {

xmlparser.go

+34
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package xmlparser
33
import (
44
"bufio"
55
"fmt"
6+
"strings"
67
"unicode/utf8"
78
)
89

@@ -340,16 +341,49 @@ func (x *XMLParser) startElement() (*XMLElement, bool, error) {
340341

341342
if x.isWS(cur) {
342343
result.Name = string(x.scratch.bytes())
344+
345+
if x.xpathEnabled {
346+
names := strings.Split(result.Name, ":")
347+
if len(names) > 1 {
348+
result.prefix = names[0]
349+
result.localName = names[1]
350+
} else {
351+
result.localName = names[0]
352+
}
353+
}
354+
343355
x.scratch.reset()
344356
goto search_close_tag
345357
}
346358

347359
if cur == '>' {
348360
if prev == '/' {
349361
result.Name = string(x.scratch.bytes()[:len(x.scratch.bytes())-1])
362+
363+
if x.xpathEnabled {
364+
names := strings.Split(result.Name, ":")
365+
if len(names) > 1 {
366+
result.prefix = names[0]
367+
result.localName = names[1]
368+
} else {
369+
result.localName = names[0]
370+
}
371+
}
372+
350373
return result, true, nil
351374
}
352375
result.Name = string(x.scratch.bytes())
376+
377+
if x.xpathEnabled {
378+
names := strings.Split(result.Name, ":")
379+
if len(names) > 1 {
380+
result.prefix = names[0]
381+
result.localName = names[1]
382+
} else {
383+
result.localName = names[0]
384+
}
385+
}
386+
353387
return result, false, nil
354388
}
355389
x.scratch.add(cur)

xmlparser_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package xmlparser
22

33
import (
44
"bufio"
5+
"bytes"
56
"fmt"
67
"os"
78
"strings"
@@ -358,6 +359,55 @@ func TestXpath(t *testing.T) {
358359
}
359360
}
360361

362+
func TestXpathNS(t *testing.T) {
363+
364+
br := bufio.NewReader(bytes.NewReader([]byte(`
365+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
366+
<soap:Body>
367+
<soap:BodyNest1>
368+
<soap:BodyNest2>
369+
</soap:BodyNest2>
370+
</soap:BodyNest1>
371+
</soap:Body>
372+
373+
<soap:Body>
374+
<soap:BodyNest1>
375+
<soap:BodyNest3 nestatt3="nestatt3val">
376+
</soap:BodyNest3>
377+
</soap:BodyNest1>
378+
</soap:Body>
379+
380+
</soap:Envelope>
381+
`)))
382+
383+
str := NewXMLParser(br, "soap:Envelope").EnableXpath()
384+
for xml := range str.Stream() {
385+
386+
if list, err := xml.SelectElements("soap:Body"); len(list) != 2 || err != nil {
387+
t.Fatal("soap:Body != 2")
388+
}
389+
390+
if list, err := xml.SelectElements("./soap:Body/soap:BodyNest1"); len(list) != 2 || err != nil {
391+
t.Fatal("/soap:Body/soap:BodyNest1 != 2")
392+
}
393+
394+
if list, err := xml.SelectElements("./soap:Body/soap:BodyNest1/soap:BodyNest2"); len(list) != 1 || err != nil {
395+
t.Fatal("/soap:Body/soap:BodyNest1/soap:BodyNest2 != 1")
396+
}
397+
398+
list, err := xml.SelectElements("./soap:Body/soap:BodyNest1/soap:BodyNest3")
399+
if len(list) != 1 || err != nil {
400+
t.Fatal("/soap:Body/soap:BodyNest1/soap:BodyNest3 != 1")
401+
}
402+
403+
if list[0].Attrs["nestatt3"] != "nestatt3val" {
404+
t.Fatal("nestatt3 attiribute test failed")
405+
}
406+
407+
}
408+
409+
}
410+
361411
func Benchmark1(b *testing.B) {
362412

363413
for n := 0; n < b.N; n++ {

0 commit comments

Comments
 (0)