// TransformXML parses the XML tree, traverses it and calls TransformFunc // on each XML token, writing the output to the writer, resulting in a // transformed XML tree func TransformXML(decoder *xml.Decoder, encoder *xml.Encoder, fn TransformFunc) error { parentNodes := &NodeList{} for { token, err := decoder.Token() if err != nil { if err != io.EOF { return trace.Wrap(err) } break } for _, t := range fn(parentNodes, token) { if err := encoder.EncodeToken(t); err != nil { return err } } switch e := token.(type) { case xml.StartElement: parentNodes.Push(e) case xml.EndElement: parentNodes.Pop() } } encoder.Flush() return nil }
func NewTree(dec *xml.Decoder) (Node, error) { var stack []*Element // stack of elements var result *Element for { tok, err := dec.Token() if err == io.EOF { break } else if err != nil { return nil, err } switch tok := tok.(type) { case xml.StartElement: newElem := &Element{tok.Name, tok.Attr, []Node{}} if len(stack) > 0 { elem := stack[len(stack)-1] elem.Children = append(elem.Children, newElem) } stack = append(stack, newElem) if result == nil { result = newElem } case xml.EndElement: stack = stack[:len(stack)-1] // pop case xml.CharData: if len(stack) == 0 { continue } elem := stack[len(stack)-1] elem.Children = append(elem.Children, CharData(tok)) } } return result, nil }
func (x *XmlNode) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { x.Name = getName(start.Name) x.Attrs = map[string]string{} for _, attr := range start.Attr { x.Attrs[getName(attr.Name)] = attr.Value } token, err := d.Token() for token != start.End() { if err != nil { return err } next, ok := token.(xml.StartElement) if ok { child := XmlNode{} err = child.UnmarshalXML(d, next) if err != nil { return err } x.Children = append(x.Children, child) } else { text, ok := token.(xml.CharData) if ok { x.Children = append(x.Children, TextNode(string([]byte(text)))) } } token, err = d.Token() } return nil }
func readOptiongroup(attributes []xml.Attr, dec *xml.Decoder) *Optiongroup { og := &Optiongroup{} og.ShortDescription = make(map[string]string) forloop: for { t, err := dec.Token() if err != nil { break } switch v := t.(type) { case xml.StartElement: switch v.Name.Local { case "shortdescription": lang, text := readShortDescription(v.Attr, dec) og.ShortDescription[lang] = text case "classoption": og.Classoption = append(og.Classoption, readClassoption(v.Attr, dec)) } case xml.EndElement: if v.Name.Local == "optiongroup" { break forloop } } } return og }
func readVariant(attributes []xml.Attr, dec *xml.Decoder) Variant { variant := Variant{} variant.Description = make(map[string]template.HTML) for _, attribute := range attributes { if attribute.Name.Local == "name" { variant.Name = attribute.Value } } for { t, err := dec.Token() if err != nil { break } switch v := t.(type) { case xml.StartElement: switch v.Name.Local { case "argument": variant.Arguments = append(variant.Arguments, readArgument(v.Attr, dec)) case "description": lang, text := readDescription(v.Attr, dec) variant.Description[lang] = text } case xml.EndElement: if v.Name.Local == "variant" { return variant } } } return variant }
func getStructMember(parser *xml.Decoder) (member Struct) { var token xml.Token token, _ = parser.Token() member = Struct{} for { switch t := token.(type) { case xml.StartElement: if t.Name.Local == "name" { member["name"], _ = getElementValue(parser) } if t.Name.Local == "value" { member["value"], _ = getValue(parser) } case xml.EndElement: if t.Name.Local == "member" { return member } } token, _ = parser.Token() } return }
func XMLText(decoder *xml.Decoder) (string, error) { r := "" for { token, err := decoder.Token() if err == io.EOF { return r, io.EOF } switch token := token.(type) { case xml.EndElement: return r, nil case xml.CharData: r += string(token) case xml.StartElement: sub, err := XMLText(decoder) r += sub if err != nil { return r, err } case xml.Comment: // ignore case xml.ProcInst: // ignore case xml.Directive: // ignore default: panic("unknown token") } } }
func readTaxonLineage(dec *xml.Decoder, tx *taxon) error { for tk, err := dec.Token(); ; tk, err = dec.Token() { if err != nil { return err } switch t := tk.(type) { case xml.StartElement: if t.Name.Local == "taxon" { for _, at := range t.Attr { switch at.Name.Local { case "taxId": tx.par = append(tx.par, at.Value) case "scientificName": tx.lin = append(tx.lin, at.Value) } } } case xml.EndElement: if t.Name.Local != "taxon" { return nil } } } }
// UnmarshalXML function unmarshal an <album-list> XML fragment to a Map[string]*Album func (am *AlbumMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { // result m := map[string]*Album{} LOOP: for { token, err := d.Token() if err != nil { return err } switch t := token.(type) { case xml.StartElement: if t.Name.Local == "album" { a := Album{} elmt := xml.StartElement(t) d.DecodeElement(&a, &elmt) m[a.ID] = &a } case xml.EndElement: if t.Name.Local == "album-list" { break LOOP } } } *am = AlbumMap(m) return nil }
func readXmlText(decoder *xml.Decoder) (string, error) { var context string for { token, err := decoder.Token() if nil != err { return context, err } switch v := token.(type) { case xml.EndElement: return context, nil case xml.CharData: context = string(v) case xml.StartElement: switch v.Name.Local { case "Datetime": txt, e := readXmlText(decoder) if nil != e { return "", e } if e = exitElement(decoder, 0); nil != e { return txt, e } return txt, nil default: return context, errors.New("element '" + v.Name.Local + "' is not excepted, excepted is CharData") } default: return context, fmt.Errorf("token '%T' is not excepted, excepted is CharData", v) } } }
func ReadEnvelopeHeader(decoder *xml.Decoder) (string, error) { var action string for { t, err := decoder.Token() if nil != err { return "", err } switch v := t.(type) { case xml.EndElement: return action, nil case xml.StartElement: switch v.Name.Local { case "Action": action, err = readXmlText(decoder) if nil != err { return "", err } default: if e := skipElement(decoder, 0); nil != e { return "", e } } } } }
func (t *Tag) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { t.Name = start.Name t.Attr = start.Attr for { token, err := d.Token() if err != nil { if err == io.EOF { return nil } return err } switch token.(type) { case xml.StartElement: tok := token.(xml.StartElement) var data *Tag if err := d.DecodeElement(&data, &tok); err != nil { return err } t.Children = append(t.Children, data) case xml.CharData: t.Children = append(t.Children, token.(xml.CharData).Copy()) case xml.Comment: t.Children = append(t.Children, token.(xml.Comment).Copy()) } } return nil }
func WalkNodePath(dec *xml.Decoder, selector string) (xml.StartElement, error) { if selector == "" { return xml.StartElement{}, errors.New("invalid path") } splitfront := func(p string) (front string, tail string) { i := strings.IndexRune(p, '/') if i >= 0 { return p[:i], p[i+1:] } return p, "" } var nextid string nextid, selector = splitfront(selector) for { token, err := dec.Token() if err != nil { return xml.StartElement{}, err } start, isStart := token.(xml.StartElement) if isStart && strings.EqualFold(nextid, getAttr(&start, "id")) { nextid, selector = splitfront(selector) if nextid == "" { return start, nil } } } panic("unreachable") }
func getNextToken(p *xml.Decoder) (*xmlToken, error) { tag, err := p.Token() if tag == nil || err != nil { return nil, err } if tokenMap == nil { initTokenMap() } switch v := tag.(type) { case xml.StartElement: tok, err := getTagToken(v.Name.Local) if err != nil { return nil, err } return &xmlToken{token: tok, isStart: true}, nil case xml.EndElement: tok, err := getTagToken(v.Name.Local) if err != nil { return nil, err } return &xmlToken{token: tok, isStart: false}, nil case xml.CharData: return &xmlToken{token: tokenText, text: string(v)}, nil case xml.ProcInst: return &xmlToken{token: tokenProcInst}, nil default: return nil, fmt.Errorf("Not handling XML token %v (type %T)", v, v) } }
// Scan XML token stream to finc next Element (start or end) func nextElement(p *xml.Decoder) (xml.Token, error) { for { t, err := p.Token() if err != nil { return xml.StartElement{}, err } switch elem := t.(type) { case xml.StartElement, xml.EndElement: return t, nil case xml.CharData: // https://xmpp.org/rfcs/rfc6120.html#xml-whitespace // rfc6120, section 1.4: "whitespace" is used to refer to any character // or characters matching [...] SP, HTAB, CR, or LF. switch string(elem) { case " ", "\t", "\r", "\n": //TODO: consider more than one whitespace log.Println("xmpp: received whitespace ping") } case xml.ProcInst: if !(elem.Target == "xml" && strings.HasPrefix(string(elem.Inst), "version=")) { log.Printf("xmpp: received unhandled ProcInst element: target=%s inst=%s\n", elem.Target, string(elem.Inst)) } default: log.Printf("xmpp: received unhandled element: %#v\n", elem) } } }
func (e *Element) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { buf := new(bytes.Buffer) enc := xml.NewEncoder(buf) if err := enc.EncodeToken(start); err != nil { return err } for { token, err := dec.Token() if err != nil { if err == io.EOF { break } return err } if err := enc.EncodeToken(token); err != nil { return err } } if err := enc.Flush(); err != nil { return err } e.Name = start.Name.Local e.Raw = buf.Bytes() return nil }
func (c *choice) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { for { tok, err := dec.Token() if err != nil && err == io.EOF { return nil } if err != nil { return err } switch v := tok.(type) { case xml.StartElement: switch v.Name.Local { case "description": d := &description{} d.commands = c.commands dec.DecodeElement(d, &v) switch d.Lang { case "en": c.DescriptionEn = d case "de": c.DescriptionDe = d } } } } return nil }
func ReadEvent(decoder *xml.Decoder) (map[string]interface{}, error) { results := map[string]interface{}{} for { t, err := decoder.Token() if nil != err { if io.EOF == err { return results, nil } return nil, err } switch v := t.(type) { case xml.EndElement: return results, nil case xml.StartElement: switch v.Name.Local { case "System": if err = ReadEventSystemElements(decoder, results); nil != err { return nil, err } case "EventData": if err = ReadEventDataElements(decoder, results); nil != err { return nil, err } default: if err = skipElement(decoder, 0); nil != err { return nil, err } } } } }
func getArrayValue(parser *xml.Decoder) (result interface{}, err error) { var token xml.Token token, err = parser.Token() result = []interface{}{} for { switch t := token.(type) { case xml.StartElement: if t.Name.Local == "value" { var value interface{} value, err = getValue(parser) result = append(result.([]interface{}), value) } case xml.EndElement: if t.Name.Local == "array" { return result, err } } token, err = parser.Token() } return }
func parsePropertyGroup(decoder *xml.Decoder, element xml.StartElement) (string, string) { outputPath, scope := "", "" if condition, ok := getAttrValue(element, "Condition"); ok { condition = strings.ToLower(condition) if strings.Contains(condition, "debug") { scope = "debug" } else if strings.Contains(condition, "release") { scope = "release" } else { return "", "unknown" } } LOOP: for { t, _ := decoder.Token() if t == nil { break } switch se := t.(type) { case xml.StartElement: if se.Name.Local == "OutputPath" { outputPath = getCharData(decoder) } case xml.EndElement: if se.Name.Local == "PropertyGroup" { break LOOP } } } return outputPath, scope }
func (ccs *CampaignCriterions) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { cc := NegativeCampaignCriterion{} for token, err := dec.Token(); err == nil; token, err = dec.Token() { if err != nil { return err } switch start := token.(type) { case xml.StartElement: switch start.Name.Local { case "campaignId": if err := dec.DecodeElement(&cc.CampaignId, &start); err != nil { return err } case "criterion": criterion, err := criterionUnmarshalXML(dec, start) if err != nil { return err } cc.Criterion = criterion case "BidModifier": if err := dec.DecodeElement(&cc.BidModifier, &start); err != nil { return err } } } } *ccs = append(*ccs, cc) return nil }
func parseReference(decoder *xml.Decoder, element xml.StartElement) *Reference { referenceName := "" hintPath := "" if ref, ok := getAttrValue(element, "Include"); ok { referenceName = ref } LOOP: for { t, _ := decoder.Token() if t == nil { break } switch se := t.(type) { case xml.StartElement: if se.Name.Local == "HintPath" { hintPath = getCharData(decoder) } case xml.EndElement: if se.Name.Local == "Reference" { break LOOP } } } if referenceName == "" { return nil } sepIndex := strings.Index(referenceName, ",") if sepIndex >= 0 { referenceName = referenceName[:sepIndex] } return &Reference{Name: referenceName, Path: hintPath} }
func readPackageoption(attributes []xml.Attr, dec *xml.Decoder) *Packageoption { po := &Packageoption{} po.ShortDescription = make(map[string]string) for _, attribute := range attributes { switch attribute.Name.Local { case "name": po.Name = attribute.Value case "default": po.Default = attribute.Value == "yes" } } forloop: for { t, err := dec.Token() if err != nil { break } switch v := t.(type) { case xml.StartElement: switch v.Name.Local { case "shortdescription": lang, text := readShortDescription(v.Attr, dec) po.ShortDescription[lang] = text } case xml.EndElement: if v.Name.Local == "packageoption" { break forloop } } } return po }
// An <xs:annotation> element may contain zero or more <xs:documentation> // children. The xsd package joins the content of these children, separated // with blank lines. func (doc *annotation) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { buf := make([][]byte, 1) var ( tok xml.Token err error ) Loop: for { tok, err = d.Token() if err != nil { break } switch tok := tok.(type) { case xml.EndElement: break Loop case xml.StartElement: if (tok.Name != xml.Name{schemaNS, "documentation"}) { if err := d.Skip(); err != nil { return err } } var frag []byte if err := d.DecodeElement(&frag, &tok); err != nil { return err } buf = append(buf, bytes.TrimSpace(frag)) } } *doc = annotation(bytes.TrimSpace(bytes.Join(buf, []byte("\n\n")))) return err }
func readShortDescription(attributes []xml.Attr, dec *xml.Decoder) (string, string) { var lang string for _, attribute := range attributes { if attribute.Name.Local == "lang" { lang = attribute.Value } } var str string for { t, err := dec.Token() if err != nil { break } switch v := t.(type) { case xml.CharData: str += string(v) case xml.EndElement: return lang, str default: } } // never reached!?!? return lang, str }
// UnmarshalXML unmarshals UserData XML. func (u *UserData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { // Assume that UserData has the same general key-value structure as // EventData does. in := struct { Pairs []KeyValue `xml:",any"` }{} // Read tokens until we find the first StartElement then unmarshal it. for { t, err := d.Token() if err != nil { return err } if se, ok := t.(xml.StartElement); ok { err = d.DecodeElement(&in, &se) if err != nil { return err } u.Name = se.Name u.Pairs = in.Pairs d.Skip() break } } return nil }
func (c ChoiceParser) ParseList(d *xml.Decoder, start xml.StartElement, containerPtr interface{}, typeofPtr interface{}, appenderType appender) error { typeof := reflect.TypeOf(typeofPtr).Elem() container := reflect.ValueOf(containerPtr).Elem() token, err := d.Token() for token != start.End() { if err != nil { return err } next, ok := token.(xml.StartElement) if ok { item, err := c.Parse(d, next) if err != nil { return err } val := reflect.ValueOf(item) if !val.Type().Implements(typeof) { return fmt.Errorf("Item is not a valid %v.", typeof.Name()) } appendFn := appenders[appenderType] appendFn(container, val) } token, err = d.Token() } return nil }
func extractCombinations(dec *xml.Decoder, terms *[]string) { prefix := "" emitted := false for { token, err := dec.Token() if err != nil { if !emitted && prefix != "" { *terms = append(*terms, prefix) } return } if _, isEnd := token.(xml.EndElement); isEnd { if !emitted && prefix != "" { *terms = append(*terms, prefix) } return } if start, isStart := token.(xml.StartElement); isStart { if start.Name.Local == "indexterm" { emitted = true if prefix != "" { suffix, _ := xmltext(dec) *terms = append(*terms, prefix+":"+suffix) } } else { panic("unhandled keyword:" + start.Name.Local) } } if data, isData := token.(xml.CharData); isData { prefix = string(data) } } }
func (nagc *NegativeAdGroupCriterion) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { for token, err := dec.Token(); err == nil; token, err = dec.Token() { if err != nil { return err } switch start := token.(type) { case xml.StartElement: tag := start.Name.Local switch tag { case "adGroupId": if err := dec.DecodeElement(&nagc.AdGroupId, &start); err != nil { return err } case "criterionUse": if err := dec.DecodeElement(&nagc.CriterionUse, &start); err != nil { return err } case "criterion": criterion, err := criterionUnmarshalXML(dec, start) if err != nil { return err } nagc.Criterion = criterion case "AdGroupCriterion.Type": break default: return fmt.Errorf("unknown NegativeAdGroupCriterion field %s", tag) } } } return nil }
func (this *Pair) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { s, err := skipToStart(d) if err != nil { return err } this.Left = &NameOrPattern{} if err := this.Left.unmarshalXML(d, *s); err != nil { return err } s, err = skipToStart(d) if err != nil { return err } this.Right = &NameOrPattern{} if err := this.Right.unmarshalXML(d, *s); err != nil { return err } for { t, err := d.Token() if err != nil { return err } e, ok := t.(xml.EndElement) if ok && e.Name.Local == start.Name.Local { break } } return nil }