moovweb/gokogiri

Node.Search() uses the wrong XPath context

sorin-ionescu opened this issue · 7 comments

Node.Search() should create a new XPath context using the current node instead of using the document context to allow searching from the current node.

Thanks for your bug report! We've created a ticket in our bug tracker for this and will evaluate it in the next coming weeks.

Sorin, do you still have this issue after upgrading libxml2?

Yes, this is not a libxml2 issue. You're using the document xpath context all the time. I read it in the Go code.

Do you have problems with specific xpaths?

I think that we need to pass the document when creating an XPath context. Refer to the function:

xmlXPathContextPtr  xmlXPathNewContext  (xmlDocPtr doc)

in http://xmlsoft.org/html/libxml-xpath.html

When evaluating the XPath, I set the current node of the context to be the node where the XPath is evaluated.

xpath.ContextPtr.node = (*C.xmlNode)(nodePtr) 

and

http://xmlsoft.org/html/libxml-xpath.html#xmlXPathContext

When I tested gokogiri's XPATH, I was getting results from the document root instead of the current node.

What XPath was that? I want to try it.

This was either fixed or is not a problem. I thought I had the same issue, but my XPath was slightly off. Below is a simple test program showing the context is correct; it prints "foo\nbar\n---" and only that, as expected:

package main

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

var file = "<foo><bar></bar</foo>";

func main() {
    doc, _ := gokogiri.ParseXml([]byte(file))

  nodes, _ := doc.Search("/foo")
    for n := range nodes {
        fmt.Println(nodes[n].Name())
        subnodes, _ := nodes[n].Search("bar")
        for s := range subnodes {
            fmt.Println(subnodes[s].Name())
        }
    }

  fmt.Println("---")

  nodes, _ = doc.Search("bar")
    for n := range nodes {
        fmt.Println(nodes[n].Name())
    }
}