func ExampleElement_Search() { data := ` <Staff> <Person> <FullName>Ira Glass</FullName> </Person> <Person> <FullName>Tom Magliozzi</FullName> </Person> <Person> <FullName>Terry Gross</FullName> </Person> </Staff> ` root, err := xmltree.Parse([]byte(data)) if err != nil { log.Fatal(err) } for _, el := range root.Search("", "FullName") { fmt.Printf("%s\n", el.Content) } // Output: // Ira Glass // Tom Magliozzi // Terry Gross }
// Imports reads an XML document containing one or more <schema> // elements and returns a list of canonical XML name spaces that // the schema imports or includes, along with a URL for the schema, // if provided. func Imports(data []byte) ([]Ref, error) { var result []Ref root, err := xmltree.Parse(data) if err != nil { return nil, err } for _, v := range root.Search(schemaNS, "import") { s := Ref{v.Attr("", "namespace"), v.Attr("", "schemaLocation")} result = append(result, s) } var schema []*xmltree.Element if (root.Name == xml.Name{schemaNS, "schema"}) { schema = []*xmltree.Element{root} } else { schema = root.Search(schemaNS, "schema") } for _, tree := range schema { ns := tree.Attr("", "targetNamespace") for _, v := range tree.Search(schemaNS, "include") { s := Ref{ns, v.Attr("", "schemaLocation")} result = append(result, s) } } return result, nil }
// Parse reads XML documents containing one or more <schema> // elements. The returned slice has one Schema for every <schema> // element in the documents. Parse will not fetch schema used in // <import> or <include> statements; use the Imports function to // find any additional schema documents required for a schema. func Parse(docs ...[]byte) ([]Schema, error) { docs = append(docs, StandardSchema...) var ( result = make([]Schema, 0, len(docs)) schema = make(map[string]*xmltree.Element, len(docs)) parsed = make(map[string]Schema, len(docs)) types = make(map[xml.Name]Type) ) for _, data := range docs { var add []*xmltree.Element root, err := xmltree.Parse(data) if err != nil { return nil, err } if (root.Name == xml.Name{schemaNS, "schema"}) { add = []*xmltree.Element{root} } else { add = root.Search(schemaNS, "schema") } // We don't explicitly handle <include> declarations. // however, by merging documents with the same target // namespace together. This saves us some code, but // to properly handle <redefine> declarations and // schema without target namespaces, we would have to // do it another way. for _, s := range add { ns := s.Attr("", "targetNamespace") if v, ok := schema[ns]; !ok { schema[ns] = s } else { s.Children = append(s.Children, v.Children...) schema[ns] = s } } } for tns, root := range schema { s := Schema{TargetNS: tns, Types: make(map[xml.Name]Type)} if err := s.parse(root, schema); err != nil { return nil, err } parsed[tns] = s } for _, s := range parsed { for _, t := range s.Types { types[XMLName(t)] = t } } for _, s := range parsed { if err := s.resolvePartialTypes(types); err != nil { return nil, err } result = append(result, s) } return result, nil }
func ExampleElement_SearchFunc() { data := ` <People> <Person> <FullName>Grace R. Emlin</FullName> <Email where="home"> <Addr>[email protected]</Addr> </Email> <Email where='work'> <Addr>[email protected]</Addr> </Email> </Person> <Person> <FullName>Michael P. Thompson</FullName> <Email where="home"> <Addr>[email protected]</Addr> </Email> <Email where='work'> <Addr>[email protected]</Addr> <Addr>[email protected]</Addr> </Email> </Person> </People> ` root, err := xmltree.Parse([]byte(data)) if err != nil { log.Fatal(err) } workEmails := root.SearchFunc(func(el *xmltree.Element) bool { return el.Name.Local == "Email" && el.Attr("", "where") == "work" }) for _, el := range workEmails { for _, addr := range el.Children { fmt.Printf("%s\n", addr.Content) } } // Output: // [email protected] // [email protected] // [email protected] }
func lookupTargetNS(data ...[]byte) []string { var result []string for _, doc := range data { tree, err := xmltree.Parse(doc) if err != nil { continue } outer := xmltree.Element{ Children: []xmltree.Element{*tree}, } elts := outer.Search("http://www.w3.org/2001/XMLSchema", "schema") for _, el := range elts { ns := el.Attr("", "targetNamespace") if ns != "" { result = append(result, ns) } } } return result }
func ExampleElement_Resolve() { data := ` <collection xmlns:ns="http://ns1.net/"> <record xmlns:ns="http://ns2.net/"> <name>Old Town</name> <artist xmlns:ns="http://ns3.net/"> <name>Mustafa Grits</name> </artist> </record> <record xmlns:ns="http://ns4.net/"> <name>New Town</name> </record> </collection> ` root, err := xmltree.Parse([]byte(data)) if err != nil { log.Fatal(err) } // Flatten the tree in depth-first order flattened := root.SearchFunc(func(*xmltree.Element) bool { return true }) fmt.Printf("%s <%s>\n", root.Resolve("ns:foo").Space, root.Name.Local) for _, el := range flattened { fmt.Printf("%s <%s>\n", el.Resolve("ns:foo").Space, el.Name.Local) } // Output: // http://ns1.net/ <collection> // http://ns2.net/ <record> // http://ns2.net/ <name> // http://ns3.net/ <artist> // http://ns3.net/ <name> // http://ns4.net/ <record> // http://ns4.net/ <name> }