// Produce a C.xmlXPathObjectPtr suitable for passing to libxml2 func (n Nodeset) ToXPathNodeset() (ret C.xmlXPathObjectPtr) { ret = C.xmlXPathNewNodeSet(nil) for _, node := range n { C.xmlXPathNodeSetAdd(ret.nodesetval, (*C.xmlNode)(node.NodePtr())) } return }
// Produce a C.xmlXPathObjectPtr marked as a ResultValueTree, suitable for passing to libxml2 func (n Nodeset) ToXPathValueTree() (ret C.xmlXPathObjectPtr) { if len(n) == 0 { ret = C.xmlXPathNewValueTree(nil) return } ret = C.xmlXPathNewValueTree(nil) for _, node := range n { C.xmlXPathNodeSetAdd(ret.nodesetval, (*C.xmlNode)(node.NodePtr())) } //this hack-ish looking line tells libxml2 not to free the RVT //if we don't do this we get horrible double-free crashes everywhere ret.boolval = 0 return }
// Convert an arbitrary value into a C.xmlXPathObjectPtr // Unrecognised and nil values are converted to empty node sets. func ValueToXPathObject(val interface{}) (ret C.xmlXPathObjectPtr) { if val == nil { //return the empty node set ret = C.xmlXPathNewNodeSet(nil) return } switch v := val.(type) { case unsafe.Pointer: return (C.xmlXPathObjectPtr)(v) case []unsafe.Pointer: ptrs := v if len(ptrs) > 0 { //default - return a node set ret = C.xmlXPathNewNodeSet(nil) for _, p := range ptrs { C.xmlXPathNodeSetAdd(ret.nodesetval, (*C.xmlNode)(p)) } } else { ret = C.xmlXPathNewNodeSet(nil) return } case float64: ret = C.xmlXPathNewFloat(C.double(v)) case string: xpathBytes := GetCString([]byte(v)) xpathPtr := unsafe.Pointer(&xpathBytes[0]) ret = C.xmlXPathNewString((*C.xmlChar)(xpathPtr)) default: typ := reflect.TypeOf(val) // if a pointer to a struct is passed, get the type of the dereferenced object if typ.Kind() == reflect.Ptr { typ = typ.Elem() } //log the unknown type, return an empty node set //fmt.Println("go-resolve wrong-type", typ.Kind()) ret = C.xmlXPathNewNodeSet(nil) } return }