//Implementation of document() from XSLT spec func XsltDocumentFn(context xpath.VariableScope, args []interface{}) interface{} { if len(args) < 1 { return nil } c := context.(*ExecutionContext) switch doc := args[0].(type) { case string: if doc == "" { nodeset := xml.Nodeset{c.Style.Doc} return nodeset.ToPointers() } input := c.FetchInputDocument(doc, false) if input != nil { nodeset := xml.Nodeset{input} return nodeset.ToPointers() } return nil case []unsafe.Pointer: n := xml.NewNode(doc[0], nil) location := n.Content() input := c.FetchInputDocument(location, true) if input != nil { nodeset := xml.Nodeset{input} return nodeset.ToPointers() } fmt.Println("DOCUMENT", location) } return nil }
func EXSLTnodeset(context xpath.VariableScope, args []interface{}) interface{} { if len(args) < 1 { return nil } c := context.(*ExecutionContext) nodes := args[0] switch v := nodes.(type) { case []unsafe.Pointer: if len(v) == 0 { return nil } fauxroot := c.Output.CreateElementNode("VARIABLE") for _, node := range v { n := xml.NewNode(node, nil) fauxroot.AddChild(n) } out := xml.Nodeset{fauxroot} return out.ToPointers() default: out := fmt.Sprintf("%v", v) fmt.Println("invalid argument to exslt:nodeset", out) } return nodes }
func (context *ExecutionContext) EvalXPathAsNodeset(xmlNode xml.Node, data interface{}) (result xml.Nodeset, err error) { _, err = context.EvalXPath(xmlNode, data) if err != nil { return nil, err } nodePtrs, err := context.XPathContext.ResultAsNodeset() if err != nil { return nil, err } var output xml.Nodeset for _, nodePtr := range nodePtrs { output = append(output, xml.NewNode(nodePtr, xmlNode.MyDocument())) } result = output return }
// util function because we can't assume we're actually getting a string func argValToString(val interface{}) (out string) { if val == nil { return } switch v := val.(type) { case string: return v case []unsafe.Pointer: if len(v) == 0 { return } n := xml.NewNode(v[0], nil) out = n.Content() default: out = fmt.Sprintf("%v", v) } return }
func (context *ExecutionContext) EvalXPath(xmlNode xml.Node, data interface{}) (result interface{}, err error) { switch data := data.(type) { case string: if xpathExpr := xpath.Compile(data); xpathExpr != nil { defer xpathExpr.Free() result, err = context.EvalXPath(xmlNode, xpathExpr) } else { err = errors.New("cannot compile xpath: " + data) } case []byte: result, err = context.EvalXPath(xmlNode, string(data)) case *xpath.Expression: xpathCtx := context.XPathContext xpathCtx.SetResolver(context) err := xpathCtx.Evaluate(xmlNode.NodePtr(), data) if err != nil { return nil, err } rt := xpathCtx.ReturnType() switch rt { case xpath.XPATH_NODESET, xpath.XPATH_XSLT_TREE: nodePtrs, err := xpathCtx.ResultAsNodeset() if err != nil { return nil, err } var output []xml.Node for _, nodePtr := range nodePtrs { output = append(output, xml.NewNode(nodePtr, xmlNode.MyDocument())) } result = output case xpath.XPATH_NUMBER: result, err = xpathCtx.ResultAsNumber() case xpath.XPATH_BOOLEAN: result, err = xpathCtx.ResultAsBoolean() default: result, err = xpathCtx.ResultAsString() } default: err = errors.New("Strange type passed to ExecutionContext.EvalXPath") } return }
func parsefragment(document xml.Document, node *xml.XmlNode, content, url []byte, options xml.ParseOption) (fragment *xml.DocumentFragment, err error) { //set up pointers before calling the C function var contentPtr, urlPtr unsafe.Pointer if len(url) > 0 { urlPtr = unsafe.Pointer(&url[0]) } var root xml.Node if node == nil { containBody := (bytes.Index(content, bodySigBytes) >= 0) content = append(fragmentWrapper, content...) contentPtr = unsafe.Pointer(&content[0]) contentLen := len(content) inEncoding := document.InputEncoding() var encodingPtr unsafe.Pointer if len(inEncoding) > 0 { encodingPtr = unsafe.Pointer(&inEncoding[0]) } htmlPtr := C.htmlParseFragmentAsDoc(document.DocPtr(), contentPtr, C.int(contentLen), urlPtr, encodingPtr, C.int(options), nil, 0) //Note we've parsed the fragment within the given document //the root is not the root of the document; rather it's the root of the subtree from the fragment html := xml.NewNode(unsafe.Pointer(htmlPtr), document) if html == nil { err = ErrFailParseFragment return } root = html if !containBody { root = html.FirstChild() html.AddPreviousSibling(root) html.Remove() //remove html otherwise it's leaked } } else { //wrap the content newContent := append(fragmentWrapperStart, content...) newContent = append(newContent, fragmentWrapperEnd...) contentPtr = unsafe.Pointer(&newContent[0]) contentLen := len(newContent) rootElementPtr := C.htmlParseFragment(node.NodePtr(), contentPtr, C.int(contentLen), urlPtr, C.int(options), nil, 0) if rootElementPtr == nil { //try to parse it as a doc fragment, err = parsefragment(document, nil, content, url, options) return } if rootElementPtr == nil { err = ErrFailParseFragment return } root = xml.NewNode(unsafe.Pointer(rootElementPtr), document) } fragment = &xml.DocumentFragment{} fragment.Node = root fragment.InEncoding = document.InputEncoding() fragment.OutEncoding = document.OutputEncoding() document.BookkeepFragment(fragment) return }