如何在Go中使用XPath从XML中获取值

28

在查看go xml包时,我没有找到这样的可能性。Go只允许定义结构树,将它们映射到XML树并使用xml.NewDecoder(myXmlString).Decode(myStruct)进行反序列化。

即使我定义了所需的Go结构树,我仍然无法使用XPath查询该树。

C#有方便的函数SelectSingleNode,允许通过指定XPath从XML树中选择值,而不必在C#类中复制整个树结构。

Go中是否有类似的功能? 如果没有,那么实现它的最简单方法是什么(可能可以重用xml包)?

4个回答

15

还有一个xmlpath包。

使用示例:

path := xmlpath.MustCompile("/library/book/isbn")
root, err := xmlpath.Parse(file)
if err != nil {
    log.Fatal(err)
}
if value, ok := path.String(root); ok {
    fmt.Println("Found:", value)
}

你知道它如何与http.Get输出一起使用吗? - Mahdi
新链接:https://pkg.go.dev/gopkg.in/xmlpath.v2 - Gwyneth Llewelyn

14

在Go的标准包中没有xpath解析功能,所以您需要使用第三方包。

我知道的一个是Gokogiri
该包基于libxml2 使用cgo

您需要导入的子包是 github.com/moovweb/gokogiri/xpath


9

虽然不是xpath,但您可以使用本机go xml encoder包从XML中读取值。您可以使用xml.Unmarshal()函数进行操作。这里提供了一个go play示例。

package main

import "fmt"
import "encoding/xml"

func main() {
    type People struct {
        Names []string `xml:"Person>FullName"`
    }

    data := `
        <People>
            <Person>
                <FullName>Jerome Anthony</FullName>
            </Person>
            <Person>
                <FullName>Christina</FullName>
            </Person>
        </People>
    `

    v := People{Names: []string{}}
    err := xml.Unmarshal([]byte(data), &v)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    fmt.Printf("Names of people: %q", v)
}

虽然这通常是一个好的答案,但我已经将其点踩了,因为OP实际上指定使用XPath语法从XML对象中检索值。这个解决方案绕过了问题,根本没有使用XPath语法! - Gwyneth Llewelyn

6

xmlquery可以使用XPath表达式从XML文档中提取数据。

package main

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

func main() {
    htmlstr := `<?xml version="1.0" ?>
    <html>
    <head>
     <title>this is a title</title>
    </head>
    <body>Hello,World</body>
    </html>`
    root, err := xmlquery.Parse(strings.NewReader(htmlstr))
    if err != nil {
         panic(err)
     }
    title := xmlquery.FindOne(root, "//title")
    fmt.Println(title.InnerText())
}

有趣的是,与@rzymek提到的xmlpath不同,@antchfx的解决方案不需要预编译XPath表达式。相反,XML查询会被缓存并在需要时重复使用。这是一种替代方法。我想知道是否有人对xmlqueryxmlpath进行了基准测试。我猜预编译的XPath表达式可能更有效率,因为它们可以用于不同的XML对象。但如果你只处理一个XML对象,xmlquery可能更具优势。看到每种方法并行使用很有趣;xmlpath似乎更符合惯用法,但xmlquery更直观。 - Gwyneth Llewelyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接