gokogiri 解析含默认命名空间的 xml 时需显式注册命名空间前缀,并在 xpath 表达式中使用该前缀,否则无法匹配节点;本文提供完整可运行示例与关键注意事项。
在使用 gokogiri(Go 语言对 libxml2 的封装)解析 XML 时,若文档包含默认命名空间(即 xmlns="http://example.com/this" 这类无前缀的声明),不能直接使用无前缀的 XPath(如 //NodeA/NodeB)进行查询——即使该命名空间未显式指定前缀,XPath 引擎仍要求所有元素都通过已注册的命名空间前缀来引用。
这是因为 XML 命名空间机制规定:默认命名空间(xmlns="...")仅作用于当前元素及其子元素,但 XPath 1.0 规范不支持“默认命名空间”语法;所有带命名空间的节点在 XPath 中必须通过前缀限定(如 ns:NodeB),且该前缀须提前注册到 XPath 上下文。
以下是完整、可直接运行的示例代码:
package main
import (
"fmt"
"github.com/moovweb/gokogiri"
"github.com/moovweb/gokogiri/xpath"
)
func main() {
// 示例 XML:含默认命名空间
xmlWithNS := `
thisthat
hello
`
doc, err := gokogiri.ParseXml([]byte(xmlWithNS))
if err != nil {
panic(err)
}
defer doc.Free()
// ✅ 关键步骤:获取 XPath 上下文并注册命名空间
xp := doc.DocXPathCtx()
xp.RegisterNamespace("ns", "http://example.com/this") // 前缀 "ns" 可任意命名,URI 必须严格匹配
// ✅ 关键步骤:XPath 必须使用注册的前缀
expr := xpath.Compile("/ns:NodeA/ns:NodeB")
nodes, err := doc.Search(expr)
if err != nil {
fmt.Printf("XPath error: %v\n", err)
return
}
// 输出匹配结果
for i, node := range nodes {
fmt.Printf("%d: %s\n", i, node.Content())
}
}输出结果:
0: thisthat 1: hello
gisterNamespace(prefix, uri);可在解析后打印文档结构辅助调试:
fmt.Println(doc.Root().Name()) // 输出: NodeA fmt.Println(doc.Root().Ns().Href()) // 输出: http://example.com/this
掌握命名空间注册与 XPath 前缀绑定,即可稳健处理各类标准 XML(如 SOAP、RSS、SVG、Office Open XML 等),让 gokogiri 成为你 Go 项目中可靠的 XML 解析利器。