如何使用gokogiri(libxml2)解析具有命名空间的xml?

3
我正在使用github.com/moovweb/gokogiri来解析XML文档。在解析var b时,以下方法有效,但是当我尝试对具有命名空间的var a执行相同操作时,没有输出。如何使用gokogiri解析具有命名空间的XML?
package main

import (
    "github.com/moovweb/gokogiri"
    "github.com/moovweb/gokogiri/xpath"
    "log"
)

func main() {
    log.SetFlags(log.Lshortfile)
    doc, _ := gokogiri.ParseXml([]byte(a))
    defer doc.Free()
    doc.SetNamespace("", "http://example.com/this")
    x := xpath.Compile(".//NodeA/NodeB")
    groups, err := doc.Search(x)
    if err != nil {
        log.Println(err)
    }
    for i, group := range groups {
        log.Println(i, group)
    }
}

var a = `<?xml version="1.0" ?><NodeA xmlns="http://example.com/this"><NodeB>thisthat</NodeB></NodeA>`
var b = `<?xml version="1.0" ?><NodeA><NodeB>thisthat</NodeB></NodeA>`

编辑#1:我也尝试了 doc.RegisterNamespace 但是得到了

doc.RegisterNamespace未定义(类型* xml.XmlDocument没有RegisterNamespace字段或方法)

x.RegisterNamespace也会得到

x.RegisterNamespace未定义(类型*xpath.Expression没有RegisterNamespace字段或方法)


1
看一下func (xpath *XPath) RegisterNamespace(prefix, href string),可能在你的查询之前,你需要RegisterNamespace("NodeA", "http://example.com/this"),然后魔法就会发生? - user918176
@user918176:似乎无法弄清楚...doc.RegisterNamespace和x.RegisterNamespace都返回错误。 - user776942
@user918176:我也尝试过SetNameSpace("NodeA","example.com/this"),但那也不起作用...空切片...(例如...NodeA不是前缀) - user776942
1个回答

7
即使XML中使用的命名空间未分配前缀(即默认情况下),您仍需要注册一个并在xpath表达式中使用它。该前缀可以是任何你喜欢的,这里我用了ns。请注意,它可以与文档中使用的前缀(如果有)不同 - 需要匹配的重要部分是命名空间字符串本身。
示例:
package main

import (
    "fmt"
    "github.com/moovweb/gokogiri"
    "github.com/moovweb/gokogiri/xpath"
)

func main() {
    doc, _ := gokogiri.ParseXml([]byte(a))
    defer doc.Free()
    xp := doc.DocXPathCtx()
    xp.RegisterNamespace("ns", "http://example.com/this")
    x := xpath.Compile("/ns:NodeA/ns:NodeB")
    groups, err := doc.Search(x)
    if err != nil {
        fmt.Println(err)
    }
    for i, group := range groups {
        fmt.Println(i, group.Content())
    }
}

var a = `<?xml version="1.0" ?><NodeA xmlns="http://example.com/this"><NodeB>thisthat</NodeB></NodeA>`

输出:

0 thisthat

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