Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing xml bug #975

Merged
merged 1 commit into from
Dec 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions private/protocol/xml/xmlutil/unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,8 @@ func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
elems := node.Children[name]

if elems == nil { // try to find the field in attributes
for _, a := range node.Attr {
if name == strings.Join([]string{a.Name.Space, a.Name.Local}, ":") {
// turn this into a text node for de-serializing
elems = []*XMLNode{{Text: a.Value}}
}
if val, ok := node.findElem(name); ok {
elems = []*XMLNode{{Text: val}}
}
}

Expand Down
39 changes: 27 additions & 12 deletions private/protocol/xml/xmlutil/xml_to_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package xmlutil

import (
"encoding/xml"
"fmt"
"io"
"sort"
)
Expand All @@ -12,6 +13,9 @@ type XMLNode struct {
Children map[string][]*XMLNode `json:",omitempty"`
Text string `json:",omitempty"`
Attr []xml.Attr `json:",omitempty"`

namespaces map[string]string
parent *XMLNode
}

// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
Expand Down Expand Up @@ -59,41 +63,52 @@ func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
slice = []*XMLNode{}
}
node, e := XMLToStruct(d, &el)
out.findNamespaces()
if e != nil {
return out, e
}
node.Name = typed.Name
node.Attr = out.Attr
node = adaptNode(node)
node.findNamespaces()
tempOut := *out
// Save into a temp variable, simply because out gets squashed during
// loop iterations
node.parent = &tempOut
slice = append(slice, node)
out.Children[name] = slice
case xml.EndElement:
if s != nil && s.Name.Local == typed.Name.Local { // matching end token
return out, nil
}
out = &XMLNode{}
}
}
return out, nil
}

func adaptNode(node *XMLNode) *XMLNode {
func (n *XMLNode) findNamespaces() {
ns := map[string]string{}
for _, a := range node.Attr {
for _, a := range n.Attr {
if a.Name.Space == "xmlns" {
ns[a.Value] = a.Name.Local
break
}
}

for i, a := range node.Attr {
if a.Name.Space == "xmlns" {
continue
}
if v, ok := ns[node.Attr[i].Name.Space]; ok {
node.Attr[i].Name.Space = v
n.namespaces = ns
}

func (n *XMLNode) findElem(name string) (string, bool) {
for node := n; node != nil; node = node.parent {
for _, a := range node.Attr {
namespace := a.Name.Space
if v, ok := node.namespaces[namespace]; ok {
namespace = v
}
if name == fmt.Sprintf("%s:%s", namespace, a.Name.Local) {
return a.Value, true
}
}
}
return node
return "", false
}

// StructToXML writes an XMLNode to a xml.Encoder as tokens.
Expand Down