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.Nodetext()
:匹配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包来:
- 解析XML文档
- 使用基本的XPath查询
- 使用比较表达式
- 使用节点轴
- 使用XPath函数
您可以根据自己的需求修改XPath表达式来查询XML文档中的不同部分。
更多关于golang实现XML文档XPath查询与解析插件库xpath的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于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
库,以获得更大的灵活性。