func main() { if len(os.Args) != 2 { fmt.Println("Usage: ", os.Args[0], "file") os.Exit(1) } file := os.Args[1] bytes, err := ioutil.ReadFile(file) checkError(err) r := strings.NewReader(string(bytes)) parser := xml.NewDecoder(r) depth := 0 for { token, err := parser.Token() if err != nil { break } switch t := token.(type) { case xml.StartElement: elmt := xml.StartElement(t) name := elmt.Name.Local printElmt(name, depth) depth++ case xml.EndElement: depth-- elmt := xml.EndElement(t) name := elmt.Name.Local printElmt(name, depth) case xml.CharData: bytes := xml.CharData(t) printElmt("\""+string([]byte(bytes))+"\"", depth) case xml.Comment: printElmt("Comment", depth) case xml.ProcInst: printElmt("ProcInst", depth) case xml.Directive: printElmt("Directive", depth) default: fmt.Println("Unknown") } } }
// SerializeXMLWithQueries Serializes text into Query struct func SerializeXMLWithQueries(d *xml.Decoder, start xml.StartElement) ([]interface{}, error) { var queries []interface{} for { if token, err := d.Token(); (err == nil) && (token != nil) { switch t := token.(type) { case xml.StartElement: e := xml.StartElement(t) q := stringToQueryStruct(e.Name.Local) err = d.DecodeElement(q, &e) queries = append(queries, q) case xml.EndElement: e := xml.EndElement(t) if e.Name.Space == "http://marklogic.com/appservices/search" && e.Name.Local == "queries" { return queries, err } } } else { return queries, err } } }
//UnmarshalXML for Match struct in a special way to handle highlighting matching text func (m *Match) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { for i := range start.Attr { attr := start.Attr[i] if attr.Name.Local == "path" { m.Path = attr.Value break } } for { if token, err := d.Token(); (err == nil) && (token != nil) { switch t := token.(type) { case xml.StartElement: var content string e := xml.StartElement(t) d.DecodeElement(&content, &e) text := Text{ Text: content, HighlightedText: e.Name.Space == searchNamespace && e.Name.Local == "highlight", } m.Text = append(m.Text, text) case xml.EndElement: e := xml.EndElement(t) if e.Name.Space == searchNamespace && e.Name.Local == "match" { return nil } case xml.CharData: b := xml.CharData(t) text := Text{ Text: string([]byte(b)), HighlightedText: false, } m.Text = append(m.Text, text) } } else { return err } } }
func main() { input := ` <person> <name> <family> Newmarch </family> <personal> Jan </personal> </name> <email type="personal"> [email protected] </email> <email type="work"> [email protected] </email> </person> ` /* if len(os.Args) != 2 { fmt.Println("Usage: ", os.Args[0], "file") os.Exit(1) } file := os.Args[1] bytes, err := ioutil.ReadFile(file) checkError(err) r := strings.NewReader(string(bytes)) */ r := strings.NewReader(input) parser := xml.NewDecoder(r) depth := 0 for { token, err := parser.Token() if err != nil { break } switch t := token.(type) { case xml.StartElement: elmt := xml.StartElement(t) name := elmt.Name.Local printElmt(name, depth) depth++ case xml.EndElement: depth-- elmt := xml.EndElement(t) name := elmt.Name.Local printElmt(name, depth) case xml.CharData: bytes := xml.CharData(t) printElmt("\""+string([]byte(bytes))+"\"", depth) case xml.Comment: printElmt("Comment", depth) case xml.ProcInst: printElmt("ProcInst", depth) case xml.Directive: printElmt("Directive", depth) default: fmt.Println("Unknown") } } }
func parseCompactResult(body io.ReadCloser, data chan []string, errs chan error, quit <-chan struct{}) (*SearchResult, error) { rets := RetsResponse{} result := &SearchResult{ Data: data, Errors: errs, RetsResponse: rets, MaxRows: false, } parser := xml.NewDecoder(body) var buf bytes.Buffer // backgroundable processing of the data into our buffer bgDataProcessing := func() { defer close(errs) defer close(data) defer body.Close() for { token, err := parser.Token() if err != nil { result.Errors <- err continue } switch t := token.(type) { case xml.StartElement: switch t.Name.Local { case "MAXROWS": result.MaxRows = true } // clear any accumulated data buf.Reset() case xml.EndElement: switch t.Name.Local { case "DATA": select { case <-quit: return case data <- ParseCompactRow(buf.String(), result.Delimiter): } case "RETS": return } case xml.CharData: bytes := xml.CharData(t) buf.Write(bytes) } } } // extract the basic content before delving into the data for { token, err := parser.Token() switch err { case nil: // nothing case io.EOF: return result, nil default: return nil, err } switch t := token.(type) { case xml.StartElement: // clear any accumulated data buf.Reset() switch t.Name.Local { case "RETS", "RETS-STATUS": rets, err := ParseRetsResponseTag(t) if err != nil { return nil, err } result.RetsResponse = *rets case "COUNT": result.Count, err = ParseCountTag(t) if err != nil { return nil, err } case "DELIMITER": result.Delimiter, err = ParseDelimiterTag(t) if err != nil { return nil, err } } case xml.EndElement: elmt := xml.EndElement(t) name := elmt.Name.Local switch name { case "COLUMNS": result.Columns = ParseCompactRow(buf.String(), result.Delimiter) go bgDataProcessing() return result, nil } case xml.CharData: bytes := xml.CharData(t) buf.Write(bytes) } } }