initial commit before refactor switch
This commit is contained in:
160
server/funcs_xmlheaders.go
Normal file
160
server/funcs_xmlheaders.go
Normal file
@@ -0,0 +1,160 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user