From dfd2ddd6717acb16b43ecde5150a7d8916ac5484 Mon Sep 17 00:00:00 2001 From: Constantin Konstantinidis Date: Tue, 5 Jul 2022 07:46:07 +0200 Subject: [PATCH] encoding/xml: allow overriding by empty namespace The namespace defined by xmlns="value" can be overridden in every included tag by the empty namespace xmlns="" without a prefix. Method to calculate indent of XML handles depth of tag and its associated namespace is still active even when no indent is required. An XMLName field in a struct means that namespace must be enforced even if empty. This occurs only on an inner tag as an override of any non-empty namespace of its outer tag. An attribute is added to have the required namespace display. Fixes #7113 Change-Id: I57f2308e98c66f04108ab136d350bdc3a6091e98 Reviewed-on: https://go-review.googlesource.com/c/go/+/108796 TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek Run-TryBot: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- src/encoding/xml/marshal.go | 5 ++++ src/encoding/xml/xml_test.go | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go index 07b6042da8..0c3cc0dc36 100644 --- a/src/encoding/xml/marshal.go +++ b/src/encoding/xml/marshal.go @@ -543,6 +543,11 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat } } + // If a name was found, namespace is overridden with an empty space + if tinfo.xmlname != nil && start.Name.Space == "" && + len(p.tags) != 0 && p.tags[len(p.tags)-1].Space != "" { + start.Attr = append(start.Attr, Attr{Name{"", xmlnsPrefix}, ""}) + } if err := p.writeStart(&start); err != nil { return err } diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go index 30fb94da6d..8205ac3148 100644 --- a/src/encoding/xml/xml_test.go +++ b/src/encoding/xml/xml_test.go @@ -1059,6 +1059,56 @@ func TestIssue12417(t *testing.T) { } } +func TestIssue7113(t *testing.T) { + type C struct { + XMLName Name `xml:""` // Sets empty namespace + } + + type A struct { + XMLName Name `xml:""` + C C `xml:""` + } + + var a A + structSpace := "b" + xmlTest := `` + t.Log(xmlTest) + err := Unmarshal([]byte(xmlTest), &a) + if err != nil { + t.Fatal(err) + } + + if a.XMLName.Space != structSpace { + t.Errorf("overidding with empty namespace: unmarshalling, got %s, want %s\n", a.XMLName.Space, structSpace) + } + if len(a.C.XMLName.Space) != 0 { + t.Fatalf("overidding with empty namespace: unmarshalling, got %s, want empty\n", a.C.XMLName.Space) + } + + var b []byte + b, err = Marshal(&a) + if err != nil { + t.Fatal(err) + } + if len(a.C.XMLName.Space) != 0 { + t.Errorf("overidding with empty namespace: marshaling, got %s in C tag which should be empty\n", a.C.XMLName.Space) + } + if string(b) != xmlTest { + t.Fatalf("overidding with empty namespace: marshalling, got %s, want %s\n", b, xmlTest) + } + var c A + err = Unmarshal(b, &c) + if err != nil { + t.Fatalf("second Unmarshal failed: %s", err) + } + if c.XMLName.Space != "b" { + t.Errorf("overidding with empty namespace: after marshaling & unmarshaling, XML name space: got %s, want %s\n", a.XMLName.Space, structSpace) + } + if len(c.C.XMLName.Space) != 0 { + t.Errorf("overidding with empty namespace: after marshaling & unmarshaling, got %s, want empty\n", a.C.XMLName.Space) + } +} + func TestIssue20396(t *testing.T) { var attrError = UnmarshalError("XML syntax error on line 1: expected attribute name in element") -- 2.50.0