Golang dynamic XML parser


xmlquery is an XPath query package for XML document, lets you extract data or evaluate from XML documents by an XPath expression.

Installation
go get github.com/antchfx/xmlquery

Example

package main

import (
	"fmt"
	"strings"

	"github.com/antchfx/xmlquery"
	"github.com/antchfx/xpath"
)

func main() {
	s := `<?xml version="1.0" encoding="UTF-8" ?>
<breakfast_menu>
	<food>
		<name price="10">Berry-Berry Belgian Waffles</name>
		<description>Light Belgian waffles</description>
		<calories>900</calories>
	</food>
	<food>
		<name price="20">French Toast</name>
		<description>Thick slices</description>
		<calories>600</calories>
	</food>
	<food>
		<name price="30">Homestyle Breakfast</name>
		<description>Two eggs, bacon or sausage</description>
		<calories>950</calories>
	</food>
</breakfast_menu>`

	doc, err := xmlquery.Parse(strings.NewReader(s))
	if err != nil {
		panic(err)
	}
	root := xmlquery.FindOne(doc, "//breakfast_menu")
	if n := root.SelectElement("//food/name"); n != nil {
		fmt.Printf("Name #%s\n", n.InnerText())
	}

	if n := root.SelectElement("//food[2]/name"); n != nil {
		fmt.Printf("Name #%s\n", n.InnerText())
	}

	for i, n := range xmlquery.Find(doc, "//food/name/@price") {
		fmt.Printf("Price #%d %s\n", i, n.InnerText())
	}

	for i, n := range xmlquery.Find(doc, "//food/calories") {
		fmt.Printf("Calories #%d %s\n", i, n.InnerText())
	}

	if n := root.SelectElement("//food[2]/name"); n != nil {
		fmt.Printf("Attr #%s\n", n.Attr)
	}

	if n := root.SelectElement("//food[2]/name"); n != nil {
		fmt.Printf("Data #%s\n", n.Data)
	}

	node := xmlquery.FindOne(doc, "//breakfast_menu/food[2]")
	if n := node.SelectElement("//description"); n != nil {
		fmt.Printf("Description #%s\n", n.InnerText())
	}

	expr, err := xpath.Compile("sum(//breakfast_menu/food/name/@price)")
	price := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(float64)
	fmt.Printf("Total price: %f\n", price)

	countexpr, err := xpath.Compile("count(//breakfast_menu/food)")
	count := countexpr.Evaluate(xmlquery.CreateXPathNavigator(doc))
	fmt.Printf("Food Node Counts: %f\n", count)
}

Output

Name #Berry-Berry Belgian Waffles
Name #French Toast
Price #0 10
Price #1 20
Price #2 30
Calories #0 900
Calories #1 600
Calories #2 950
Attr #[{{ price} 20}]
Data #name
description #Thick slices
total price: 60.000000
Food Node Counts: 3.000000
Most Helpful This Week