A lightweight XML pull parser for Go, inspired by Java's XMLPullParser. It provides fine-grained control over XML parsing with a small, cursor-style API.
- Pull-based parsing for fine-grained document control
- Scoped namespace and xml:base tracking
- Efficient navigation and element skipping
- Errors you can match with
errors.As/errors.Is
go get github.com/mmcdole/goxpp/v2v1 remains available at github.com/mmcdole/goxpp and receives critical fixes on the v1 branch.
import (
"encoding/xml"
xpp "github.com/mmcdole/goxpp/v2"
)
// Parse an RSS feed
file, _ := os.Open("feed.rss")
d := xml.NewDecoder(file)
d.Strict = false
p := xpp.New(d)
// Find the channel element
for tok, err := p.NextTag(); tok != xpp.EndDocument; tok, err = p.NextTag() {
if err != nil {
return err
}
if tok == xpp.StartTag && p.Name() == "channel" {
// Process channel contents
for tok, err = p.NextTag(); tok != xpp.EndTag; tok, err = p.NextTag() {
if err != nil {
return err
}
if tok == xpp.StartTag {
switch p.Name() {
case "title":
title, _ := p.NextText()
fmt.Printf("Feed: %s\n", title)
case "item":
// Get the item title and skip the rest
p.NextTag()
title, _ := p.NextText()
fmt.Printf("Item: %s\n", title)
p.Skip()
default:
p.Skip()
}
}
}
break
}
}StartDocument,EndDocumentStartTag,EndTagText,CommentProcessingInstruction,Directive
The v2 changes are listed in #34. In short:
- Construct with
xpp.New(*xml.Decoder); configure strictness and charset conversion on the decoder. - Cursor state moved from exported fields to methods:
p.Namebecomesp.Name(), and so on. Namespaces()maps prefix to URI;PrefixForURIcovers the reverse lookup.BaseURL()exposes the in-scope xml:base; resolving URLs against it is the caller's concern.- Advancement calls after
EndDocumentreturnio.EOF; positional failures are*xpp.ExpectError.
For detailed documentation and examples, visit pkg.go.dev.
This project is licensed under the MIT License.