在Go语言中,使用xml.Marshal时可以省略结构体的名称。

huangapple go评论86阅读模式
英文:

golang: Omit name of struct in xml.Marshal

问题

尝试为XML获取特定的输出:

<RESPONSE>
    <DELIMITER value="09"></DELIMITER>
    <COLUMNS>Id	FirstName	LastName	Company	Initials</COLUMNS>
     <DATA>87734	Some Guy	Keller Williams Realty Empire	</DATA>
     <DATA>87739	Another Guy	Level Group, Inc.	</DATA>
     <DATA>87741	Some Gal	Kian Realty NYC, LLC	</DATA>
</RESPONSE>

而我得到的是:

<RESPONSE>
 <compactData>
        <DELIMITER value="09"></DELIMITER>
        <COLUMNS>Id	FirstName	LastName	Company	Initials</COLUMNS>
        <DATA>87734	Some Guy	Keller Williams Realty Empire	</DATA>
        <DATA>87739	Another Guy	Level Group, Inc.	</DATA>
        <DATA>87741	Some Gal	Kian Realty NYC, LLC	</DATA>
 </compactData>
</RESPONSE>

我试图完全不输出 <compactData> 标签。(其他都没问题)

我要编组的结构如下:

type delimiter struct {
	Value string `xml:"value,attr"`
}

type innerData struct {
	Data string `xml:",innerxml"`
}

type compactData struct {
	Delimiter delimiter    `xml:"DELIMITER"`
	Columns   *innerData   `xml:"COLUMNS"`
	Records   []*innerData `xml:"DATA"`
}

我尝试过添加

XMLName   xml.Name

或者

XMLName   xml.Name `xml:""`

但都没有效果- xml.MarshalIndent 只是说 '是的,看起来像垃圾,取代结构名'。

我觉得我可能只需要稍微重新组织一下结构,但是对于所需的神奇结构我感到困惑。

谢谢!

编辑:<RESPONSE> 标签是在发送 http.reponse 之后添加的,完成此格式化后,尝试保持与 JSON 和 XML 编码相同的签名...

像这样:

func createResponse(obj interface{}, format string) (*Response, error) {
	var data []byte

	var f func(interface{}, string, string) ([]byte, error)

	switch format {
	case FORMAT_JSON:
		f = json.MarshalIndent
	case FORMAT_COMPACT:
		f = compact.MarshalIndent
	default:
		f = xml.MarshalIndent
	}
	data, err := f(obj, " ", "    ")
	if err != nil {
		log.Println(err)
		return nil, err
	}
	return &Response{Data: string(data)}, nil

}
英文:

Trying to get a particular output for XML:

<RESPONSE>
    <DELIMITER value="09"></DELIMITER>
    <COLUMNS>Id	FirstName	LastName	Company	Initials</COLUMNS>
     <DATA>87734	Some Guy	Keller Williams Realty Empire	</DATA>
     <DATA>87739	Another Guy	Level Group, Inc.	</DATA>
     <DATA>87741	Some Gal	Kian Realty NYC, LLC	</DATA>
</RESPONSE> 

instead I am getting:

<RESPONSE>
 <compactData>
        <DELIMITER value="09"></DELIMITER>
        <COLUMNS>Id	FirstName	LastName	Company	Initials</COLUMNS>
        <DATA>87734	Some Guy	Keller Williams Realty Empire	</DATA>
        <DATA>87739	Another Guy	Level Group, Inc.	</DATA>
        <DATA>87741	Some Gal	Kian Realty NYC, LLC	</DATA>
 </compactData>
</RESPONSE> 

I am trying not to output the <compactData> tag at all. (everything else is a-ok)

my struct that I am marshal-ing looks like this:

type delimiter struct {
	Value string `xml:"value,attr"`
}

type innerData struct {
	Data string `xml:",innerxml"`
}

type compactData struct {
	Delimiter delimiter    `xml:"DELIMITER"`
	Columns   *innerData   `xml:"COLUMNS"`
	Records   []*innerData `xml:"DATA"`
}

I have tried putting in

XMLName   xml.Name

or

XMLName   xml.Name `xml:""`

to no avail- the xml.MarshalIndent just says 'yeah that looks like crap taking the struct name instead'.

I feel as though I just may need to reorganize the struct a bit, but I am stumped as to the magic structure needed.

Thanks!

Edit: the <RESPONSE> tag is added as the http.reponse is sent, after this formatting is done, trying to keep this signature the same as JSON and XML encoding...

like so:

func createResponse(obj interface{}, format string) (*Response, error) {
	var data []byte

	var f func(interface{}, string, string) ([]byte, error)

	switch format {
	case FORMAT_JSON:
		f = json.MarshalIndent
	case FORMAT_COMPACT:
		f = compact.MarshalIndent
	default:
		f = xml.MarshalIndent
	}
	data, err := f(obj, " ", "    ")
	if err != nil {
		log.Println(err)
		return nil, err
	}
	return &Response{Data: string(data)}, nil

}

答案1

得分: 4

如果RESPONSE是另一个struct,你可以将compactData嵌入其中,并让encoding/xml按照你的要求进行处理。

type RESPONSE struct {
    compactData
}

https://play.golang.org/p/hN1hDY7pnV

更新
实际上,如果我理解正确的话,你可以通过实现xml.Marshaler接口来实现你想要的效果。例如,可以像这样实现:https://play.golang.org/p/Uwm0pP1pWh。

英文:

If RESPONSE is another struct you could embed compactData in it and let encoding/xml do what you want.

type RESPONSE struct {
	compactData
}

https://play.golang.org/p/hN1hDY7pnV

Update:
Actually you can do what you want, if I understood you correctly, by implementing the xml.Marshaler interface. E.g. something like this: https://play.golang.org/p/Uwm0pP1pWh.

huangapple
  • 本文由 发表于 2017年3月30日 02:00:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/43100853.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定