github.com/vmware/govmomi@v0.51.0/cli/esx/response.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package esx
     6  
     7  import (
     8  	"io"
     9  
    10  	"github.com/vmware/govmomi/vim25/xml"
    11  )
    12  
    13  type Values map[string][]string
    14  
    15  type Response struct {
    16  	Info   *CommandInfoMethod `json:"info"`
    17  	Values []Values           `json:"values"`
    18  	String string             `json:"string"`
    19  	Kind   string             `json:"-"`
    20  }
    21  
    22  func (v Values) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    23  	for {
    24  		t, err := d.Token()
    25  		if err != nil {
    26  			if err == io.EOF {
    27  				return nil
    28  			}
    29  			return err
    30  		}
    31  
    32  		if s, ok := t.(xml.StartElement); ok {
    33  			t, err = d.Token()
    34  			if err != nil {
    35  				return err
    36  			}
    37  
    38  			key := s.Name.Local
    39  			var val string
    40  			if c, ok := t.(xml.CharData); ok {
    41  				val = string(c)
    42  			}
    43  			v[key] = append(v[key], val)
    44  		}
    45  	}
    46  }
    47  
    48  func (s Values) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    49  	tokens := []xml.Token{start}
    50  
    51  	for key, val := range s {
    52  		field := xml.StartElement{Name: xml.Name{Local: key}}
    53  		for _, v := range val {
    54  			tokens = append(tokens, field, xml.CharData(v), field.End())
    55  		}
    56  	}
    57  
    58  	tokens = append(tokens, start.End())
    59  
    60  	for _, t := range tokens {
    61  		err := e.EncodeToken(t)
    62  		if err != nil {
    63  			return err
    64  		}
    65  	}
    66  
    67  	return nil
    68  }
    69  
    70  func (v Values) Value(name string) string {
    71  	if val, ok := v[name]; ok {
    72  		if len(val) != 0 {
    73  			return val[0]
    74  		}
    75  	}
    76  	return ""
    77  }
    78  
    79  func (r *Response) Type(start xml.StartElement) string {
    80  	for _, a := range start.Attr {
    81  		if a.Name.Local == "type" {
    82  			return a.Value
    83  		}
    84  	}
    85  	return ""
    86  }
    87  
    88  func (r *Response) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    89  	stype := r.Type(start)
    90  
    91  	if stype != "ArrayOfDataObject" {
    92  		switch stype {
    93  		case "xsd:string", "xsd:boolean", "xsd:long":
    94  			return d.DecodeElement(&r.String, &start)
    95  		}
    96  		v := Values{}
    97  		if err := d.DecodeElement(&v, &start); err != nil {
    98  			return err
    99  		}
   100  		r.Values = append(r.Values, v)
   101  		return nil
   102  	}
   103  
   104  	for {
   105  		t, err := d.Token()
   106  		if err != nil {
   107  			if err == io.EOF {
   108  				return nil
   109  			}
   110  			return err
   111  		}
   112  
   113  		if s, ok := t.(xml.StartElement); ok {
   114  			if s.Name.Local == "DataObject" {
   115  				v := Values{}
   116  				if err := d.DecodeElement(&v, &s); err != nil {
   117  					return err
   118  				}
   119  				r.Values = append(r.Values, v)
   120  			}
   121  		}
   122  	}
   123  }
   124  
   125  func (r *Response) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
   126  	kind := "ArrayOfDataObject"
   127  	native := r.String != ""
   128  	if native {
   129  		kind = "xsd:" + r.Kind
   130  	}
   131  
   132  	start := xml.StartElement{
   133  		Name: xml.Name{
   134  			Space: "urn:vim25",
   135  			Local: "obj",
   136  		},
   137  		Attr: []xml.Attr{
   138  			{
   139  				Name:  xml.Name{Local: "xmlns:xsd"},
   140  				Value: "http://www.w3.org/2001/XMLSchema",
   141  			},
   142  			{
   143  				Name:  xml.Name{Local: "xmlns:xsi"},
   144  				Value: "http://www.w3.org/2001/XMLSchema-instance",
   145  			},
   146  			{
   147  				Name:  xml.Name{Local: "xsi:type"},
   148  				Value: kind,
   149  			},
   150  		},
   151  	}
   152  
   153  	if err := e.EncodeToken(start); err != nil {
   154  		return err
   155  	}
   156  
   157  	var err error
   158  	if native {
   159  		err = e.EncodeToken(xml.CharData(r.String))
   160  	} else {
   161  		obj := xml.StartElement{
   162  			Name: xml.Name{Local: "DataObject"},
   163  			Attr: []xml.Attr{{
   164  				Name:  xml.Name{Local: "xsi:type"},
   165  				Value: r.Kind,
   166  			}},
   167  		}
   168  		err = e.EncodeElement(r.Values, obj)
   169  	}
   170  
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	return e.EncodeToken(start.End())
   176  }