// makePath finds or creates a tree of Scanners. // It returns the leaf node Scanner for the path or an error. func (s *Scanner) makePath(path string) (*Scanner, error) { names := strings.SplitN(path, ">", 2) fields := strings.Fields(names[0]) var name xml.Name switch len(fields) { case 0: if len(names) > 1 { return nil, ErrInvalidPath } return s, nil case 1: name.Local = fields[0] case 2: name.Space = fields[0] name.Local = fields[1] default: return nil, ErrInvalidPath } s2, ok := s.tree[name] if !ok { s2 = NewScanner() s.tree[name] = s2 } if len(names) == 1 { return s2.makePath("") } return s2.makePath(names[1]) }
func xfFunction(f *xpFilt, n *parser.Node) error { spl := strings.Split(n.Val.Val, ":") var name xml.Name if len(spl) == 1 { name.Local = spl[0] } else { name.Space = f.ns[spl[0]] name.Local = spl[1] } fn, ok := intfns.BuiltIn[name] if !ok { fn, ok = f.fns[name] } if ok { args := []tree.Result{} param := n.Left for param != nil { pf := xpFilt{ t: f.t, ctx: f.ctx, ns: f.ns, ctxPos: f.ctxPos, ctxSize: f.ctxSize, fns: f.fns, variables: f.variables, } res, err := exec(&pf, param.Left) if err != nil { return err } args = append(args, res) param = param.Right } filt, err := fn.Call(tree.Ctx{NodeSet: f.ctx.(tree.NodeSet), Size: f.ctxSize, Pos: f.ctxPos + 1}, args...) f.ctx = filt return err } return fmt.Errorf("Unknown function: %s", n.Val.Val) }
// SOAP arrays (and other similar types) are complex types with a single // plural element. We add a post-processing step to flatten it out and provide // marshal/unmarshal methods. func (cfg *Config) soapArrayToSlice(s spec) spec { str, ok := s.expr.(*ast.StructType) if !ok { return s } if len(str.Fields.List) != 1 { return s } slice, ok := str.Fields.List[0].Type.(*ast.ArrayType) if !ok { return s } cfg.debugf("flattening single-element slice struct type %s to []%v", s.name, slice.Elt) tag := gen.TagKey(str.Fields.List[0], "xml") xmltag := xml.Name{"", ",any"} if tag != "" { parts := strings.Split(tag, ",") if len(parts) > 0 { fields := strings.Fields(parts[0]) if len(fields) > 0 { xmltag.Local = fields[len(fields)-1] } if len(fields) > 1 { xmltag.Space = fields[0] } } } itemType := gen.ExprString(slice.Elt) unmarshal, err := gen.Func("UnmarshalXML"). Receiver("a *"+s.name). Args("d *xml.Decoder", "start xml.StartElement"). Returns("err error"). Body(` var tok xml.Token var itemTag = xml.Name{%q, %q} for tok, err = d.Token(); err == nil; tok, err = d.Token() { if tok, ok := tok.(xml.StartElement); ok { var item %s if itemTag.Local != ",any" && itemTag != tok.Name { err = d.Skip() continue } if err = d.DecodeElement(&item, &tok); err == nil { *a = append(*a, item) } } if _, ok := tok.(xml.EndElement); ok { break } } return err `, xmltag.Space, xmltag.Local, itemType).Decl() if err != nil { cfg.logf("error generating UnmarshalXML method of %s: %v", s.name, err) return s } marshal, err := gen.Func("MarshalXML"). Receiver("a *"+s.name). Args("e *xml.Encoder", "start xml.StartElement"). Returns("error"). Body(` tag := xml.StartElement{Name: xml.Name{"", "item"}} for _, elt := range *a { if err := e.EncodeElement(elt, tag); err != nil { return err } } return nil `).Decl() if err != nil { cfg.logf("error generating MarshalXML method of %s: %v", s.name, err) return s } s.expr = slice s.methods = append(s.methods, marshal) s.methods = append(s.methods, unmarshal) if helper := cfg.helper("_unmarshalArray"); helper != nil { s.methods = append(s.methods, helper) } return s }