161 lines
3.2 KiB
Go
161 lines
3.2 KiB
Go
package server
|
|
|
|
import (
|
|
`encoding/xml`
|
|
`errors`
|
|
`io`
|
|
)
|
|
|
|
/*
|
|
MarshalXML encodes an XmlHeaders as XML in the following format:
|
|
|
|
(<headers>)
|
|
<header name="SomeHeader">
|
|
<value>SomeValue</value>
|
|
</header>
|
|
<header name="SomeMultiValueHeader">
|
|
<value>Foo</value>
|
|
<value>Bar</value>
|
|
</header>
|
|
(</headers>)
|
|
|
|
For the above example, the field should be specified as `xml:"headers"`.
|
|
However, the parent element name may be whatever you wish.
|
|
*/
|
|
func (x XmlHeaders) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
|
|
|
|
var curKey string
|
|
var vals []string
|
|
var val string
|
|
var hdr xml.StartElement
|
|
var child xml.StartElement
|
|
// TODO: Does xml.EncodeElement properly escape?
|
|
// var escKBuf *bytes.Buffer
|
|
// var escVBuf *bytes.Buffer
|
|
|
|
// All values are []string, so we don't need any fancy parsing or switching or the like.
|
|
// We do need to make sure we escape, though.
|
|
|
|
if err = e.EncodeToken(start); err != nil {
|
|
return
|
|
}
|
|
|
|
if x != nil && len(x) > 0 {
|
|
// escKBuf = new(bytes.Buffer)
|
|
// escVBuf = new(bytes.Buffer)
|
|
for curKey, vals = range x {
|
|
// escKBuf.Reset()
|
|
// if err = xml.EscapeText(escKBuf, []byte(curKey)); err != nil {
|
|
// return
|
|
// }
|
|
hdr = xml.StartElement{
|
|
Name: xml.Name{
|
|
Local: xmlHdrElem,
|
|
},
|
|
Attr: []xml.Attr{
|
|
xml.Attr{
|
|
Name: xml.Name{
|
|
Local: xmlHdrElemName,
|
|
},
|
|
// Value: escKBuf.String(),
|
|
Value: curKey,
|
|
},
|
|
},
|
|
}
|
|
if err = e.EncodeToken(hdr); err != nil {
|
|
return
|
|
}
|
|
for _, val = range vals {
|
|
// escVBuf.Reset()
|
|
// if err = xml.EscapeText(escVBuf, []byte(val)); err != nil {
|
|
// return
|
|
// }
|
|
child = xml.StartElement{
|
|
Name: xml.Name{
|
|
Local: xmlHdrVal,
|
|
},
|
|
}
|
|
// if err = e.EncodeElement(escVBuf.String(), child); err != nil {
|
|
if err = e.EncodeElement(val, child); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if err = e.EncodeToken(hdr.End()); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if err = e.EncodeToken(start.End()); err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// UnmarshalXML populates an XMLHeaders from an XML representation. See MarshalXML for example XML.
|
|
func (x *XmlHeaders) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
|
|
|
var tok xml.Token
|
|
var xm XmlHeaders
|
|
var hdrNm string
|
|
var vals []string
|
|
var val *string
|
|
var nameFound bool
|
|
|
|
for {
|
|
if tok, err = d.Token(); err != nil {
|
|
if errors.Is(err, io.EOF) {
|
|
err = nil
|
|
break
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
switch elem := tok.(type) {
|
|
case xml.StartElement:
|
|
switch elem.Name.Local {
|
|
case xmlHdrElem:
|
|
nameFound = false
|
|
vals = nil
|
|
for _, a := range elem.Attr {
|
|
if a.Name.Local == xmlHdrElemName {
|
|
nameFound = true
|
|
hdrNm = a.Value
|
|
break
|
|
}
|
|
}
|
|
if !nameFound {
|
|
continue
|
|
}
|
|
case xmlHdrVal:
|
|
if !nameFound {
|
|
continue
|
|
}
|
|
if vals == nil {
|
|
vals = make([]string, 0, 1)
|
|
}
|
|
val = new(string)
|
|
if err = d.DecodeElement(val, &elem); err != nil {
|
|
return
|
|
}
|
|
vals = append(vals, *val)
|
|
}
|
|
case xml.EndElement:
|
|
if elem.Name.Local != xmlHdrElem {
|
|
continue
|
|
}
|
|
if xm == nil {
|
|
xm = make(XmlHeaders)
|
|
}
|
|
xm[hdrNm] = vals
|
|
}
|
|
}
|
|
|
|
if xm != nil {
|
|
*x = xm
|
|
}
|
|
|
|
return
|
|
}
|