golang实现XML文档XPath查询与解析插件库xpath的使用

Golang实现XML文档XPath查询与解析插件库xpath的使用

XPath是一个Go语言包,提供了使用XPath表达式从XML、HTML或其他文档中选择节点的功能。

实现方式

  • htmlquery - 用于HTML文档的XPath查询包
  • xmlquery - 用于XML文档的XPath查询包
  • jsonquery - 用于JSON文档的XPath查询包

支持的功能

基本XPath模式

基本XPath模式覆盖了大多数样式表所需的90%情况:

  • node:选择所有名为node的子元素
  • *:选择所有子元素
  • @attr:选择attr属性
  • @*:选择所有属性
  • node():匹配org.w3c.dom.Node
  • text():匹配org.w3c.dom.Text节点
  • comment():匹配注释
  • .:选择当前节点
  • ..:选择当前节点的父节点
  • /:选择文档节点
  • a[expr]:只选择匹配a同时满足expr表达式的节点
  • a[n]:选择第n个匹配a的节点
  • a/b:为每个匹配a的节点添加匹配b的节点到结果中
  • a//b:为每个匹配a的节点添加匹配b的后代节点到结果中
  • //b:返回文档中所有匹配b的节点
  • a|b:所有匹配a或b的节点(并集操作)
  • (a, b, c):评估每个操作数并按顺序将结果序列连接成单个结果序列
  • (a/b):选择所有匹配节点作为分组集

节点轴

  • child::*:选择当前节点的子节点
  • descendant::*:选择当前节点的后代节点(等同于//)
  • descendant-or-self::*:选择包括当前节点在内的后代节点
  • attribute::*:选择当前元素的属性(等同于@*)
  • following-sibling::*:选择当前节点之后的节点
  • preceding-sibling::*:选择当前节点之前的节点
  • following::*:选择文档顺序中第一个匹配的后续节点(不包括后代)
  • preceding::*:选择文档顺序中第一个匹配的前驱节点(不包括祖先)
  • parent::*:选择匹配的父节点
  • ancestor::*:选择匹配的祖先节点
  • ancestor-or-self::*:选择包括当前节点在内的祖先节点
  • self::*:选择当前节点(等同于.)

表达式

gxpath支持三种类型:number、boolean、string。

  • path:基于路径选择节点
  • a = b:标准比较
  • a + b:算术表达式
  • a or b:布尔或运算
  • a and b:布尔与运算
  • (expr):括号表达式
  • fun(arg1, ..., argn):函数调用

示例代码

下面是一个使用xmlquery包进行XPath查询的完整示例:

package main

import (
	"fmt"
	"strings"
	
	"github.com/antchfx/xmlquery"
)

func main() {
	// XML文档示例
	xml := `<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="web">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>`

	// 解析XML文档
	doc, err := xmlquery.Parse(strings.NewReader(xml))
	if err != nil {
		panic(err)
	}

	// 示例1: 选择所有book节点
	nodes := xmlquery.Find(doc, "//book")
	for i, n := range nodes {
		fmt.Printf("Book %d: %s\n", i+1, n.OutputXML(true))
	}

	// 示例2: 选择价格大于35的书籍
	expr, err := xmlquery.Compile("//book[price > 35]")
	if err != nil {
		panic(err)
	}
	expensiveBooks := expr.SelectNodes(doc)
	for _, book := range expensiveBooks {
		title := xmlquery.FindOne(book, "title")
		price := xmlquery.FindOne(book, "price")
		fmt.Printf("Expensive book: %s (%s)\n", title.InnerText(), price.InnerText())
	}

	// 示例3: 使用轴选择节点
	// 选择所有book节点的title子节点
	titles := xmlquery.Find(doc, "//book/child::title")
	for _, title := range titles {
		fmt.Printf("Title: %s\n", title.InnerText())
	}

	// 示例4: 使用函数
	// 计算书籍总数
	count := xmlquery.Find(doc, "count(//book)")
	fmt.Printf("Total books: %s\n", count[0].InnerText())
}

这个示例展示了如何使用xmlquery包来:

  1. 解析XML文档
  2. 使用基本的XPath查询
  3. 使用比较表达式
  4. 使用节点轴
  5. 使用XPath函数

您可以根据自己的需求修改XPath表达式来查询XML文档中的不同部分。


更多关于golang实现XML文档XPath查询与解析插件库xpath的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现XML文档XPath查询与解析插件库xpath的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang实现XML文档XPath查询与解析

在Golang中处理XML文档的XPath查询,可以使用github.com/antchfx/xpath库,这是一个功能强大且高效的XPath实现。下面我将详细介绍如何使用这个库进行XML文档的XPath查询与解析。

安装xpath库

首先需要安装xpath库:

go get github.com/antchfx/xpath

基本使用方法

1. 解析XML文档

package main

import (
	"encoding/xml"
	"fmt"
	"strings"

	"github.com/antchfx/xpath"
)

func main() {
	// XML示例数据
	data := `
	<bookstore>
		<book category="cooking">
			<title lang="en">Everyday Italian</title>
			<author>Giada De Laurentiis</author>
			<year>2005</year>
			<price>30.00</price>
		</book>
		<book category="children">
			<title lang="en">Harry Potter</title>
			<author>J.K. Rowling</author>
			<year>2005</year>
			<price>29.99</price>
		</book>
	</bookstore>
	`

	// 解析XML文档
	doc := &xmlquery.Node{}
	if err := xmlquery.Unmarshal([]byte(data), doc); err != nil {
		panic(err)
	}

	// 创建XPath表达式
	expr, err := xpath.Compile("//book[price>29]/title/text()")
	if err != nil {
		panic(err)
	}

	// 执行XPath查询
	iter := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(*xpath.NodeIterator)
	for iter.MoveNext() {
		fmt.Println(iter.Current().Value())
	}
}

2. 常用XPath查询示例

// 1. 获取所有book节点
expr := xpath.MustCompile("//book")
iter := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(*xpath.NodeIterator)

// 2. 获取价格大于29的书籍标题
expr = xpath.MustCompile("//book[price>29]/title/text()")

// 3. 获取特定语言的标题
expr = xpath.MustCompile("//title[@lang='en']")

// 4. 获取第一个book节点
expr = xpath.MustCompile("//book[1]")

// 5. 获取所有作者
expr = xpath.MustCompile("//author/text()")

3. 处理查询结果

// 遍历查询结果
iter := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(*xpath.NodeIterator)
for iter.MoveNext() {
    node := iter.Current().(*xmlquery.Node)
    switch node.Type {
    case xmlquery.TextNode:
        fmt.Println("Text:", node.Data)
    case xmlquery.ElementNode:
        fmt.Println("Element:", node.Data)
        for _, attr := range node.Attr {
            fmt.Printf("  Attr: %s=%s\n", attr.Name.Local, attr.Value)
        }
    }
}

高级用法

1. 自定义函数

// 注册自定义XPath函数
xpath.RegisterFunction("contains-ignore-case", func(args ...interface{}) interface{} {
    if len(args) != 2 {
        return false
    }
    s1 := args[0].(string)
    s2 := args[1].(string)
    return strings.Contains(strings.ToLower(s1), strings.ToLower(s2))
})

// 使用自定义函数
expr := xpath.MustCompile("//book[contains-ignore-case(title, 'harry')]")

2. 性能优化

对于大型XML文档,可以使用流式解析:

import "github.com/antchfx/xmlquery"

// 流式解析大型XML文件
f, err := os.Open("large.xml")
if err != nil {
    panic(err)
}
defer f.Close()

doc, err := xmlquery.Parse(f)
if err != nil {
    panic(err)
}

完整示例

下面是一个完整的示例,演示如何从XML文件中查询并处理数据:

package main

import (
	"fmt"
	"log"

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

func main() {
	// 示例XML数据
	data := `
	<catalog>
		<product id="1">
			<name>Laptop</name>
			<price>999.99</price>
			<stock>15</stock>
		</product>
		<product id="2">
			<name>Smartphone</name>
			<price>699.99</price>
			<stock>32</stock>
		</product>
		<product id="3">
			<name>Tablet</name>
			<price>399.99</price>
			<stock>12</stock>
		</product>
	</catalog>
	`

	// 解析XML
	doc, err := xmlquery.Parse(strings.NewReader(data))
	if err != nil {
		log.Fatal(err)
	}

	// 查询价格低于700的产品名称
	expr := xpath.MustCompile("//product[price<700]/name/text()")
	iter := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(*xpath.NodeIterator)

	fmt.Println("Affordable products:")
	for iter.MoveNext() {
		fmt.Println("-", iter.Current().Value())
	}

	// 查询库存少于20的产品ID
	expr = xpath.MustCompile("//product[stock<20]/@id")
	iter = expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(*xpath.NodeIterator)

	fmt.Println("\nLow stock product IDs:")
	for iter.MoveNext() {
		fmt.Println("-", iter.Current().Value())
	}
}

总结

github.com/antchfx/xpath库为Golang提供了强大的XPath查询能力,可以方便地从XML文档中提取和处理数据。通过本文介绍的基本查询、结果处理、自定义函数和性能优化等方法,您可以高效地实现各种XML处理需求。

对于更复杂的XML处理场景,您还可以考虑结合使用encoding/xml标准库和xpath库,以获得更大的灵活性。

回到顶部