英文:
Array of struct in XML with no wrapping node?
问题
我有一个客户,他们的 XML 中似乎想要一个库存数组,但是每个项目都在另一个项目之后列出,没有包装节点。
这是我正在做的一个示例,但是每个项目都有一个包装节点。有没有办法让它们都在 "root" 下面直接列出来?
测试代码:
package main
import (
"encoding/xml"
"fmt"
"os"
"strconv"
)
func main() {
type InventoryItem struct {
XMLName xml.Name
ItemName string `xml:"Name"`
ItemDescription string `xml:"Description"`
}
type XMLEnvelop struct {
XMLName xml.Name `xml:"root"`
Inventory []InventoryItem `xml:",any"`
Records int `xml:"records"`
}
var items []InventoryItem
for i := 1; i < 6; i++ {
items = append(items, InventoryItem{XMLName: xml.Name{Local: "item" + strconv.Itoa(i)}, ItemName: "Test " + strconv.Itoa(i), ItemDescription: "Description " + strconv.Itoa(i)})
}
v := &XMLEnvelop{Records: 1, Inventory: items}
output, err := xml.MarshalIndent(v, "", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
// Write the output to check
os.Stdout.Write(output)
//Here is where I would make the request
}
测试输出:
<root>
<item1>
<Name>Test 1</Name>
<Description>Description 1</Description>
</item1>
<item2>
<Name>Test 2</Name>
<Description>Description 2</Description>
</item2>
<item3>
<Name>Test 3</Name>
<Description>Description 3</Description>
</item3>
<item4>
<Name>Test 4</Name>
<Description>Description 4</Description>
</item4>
<item5>
<Name>Test 5</Name>
<Description>Description 5</Description>
</item5>
<records>1</records>
</root>
这是他们似乎在寻找的输出...不管出于什么原因。
<root>
<Name>Test 1</Name>
<Description>Description 1</Description>
<Name>Test 2</Name>
<Description>Description 2</Description>
<Name>Test 3</Name>
<Description>Description 3</Description>
<Name>Test 4</Name>
<Description>Description 4</Description>
<Name>Test 5</Name>
<Description>Description 5</Description>
<records>1</records>
</root>
Go Playground: https://play.golang.org/p/3DRUaBFEQvC
英文:
I have a customer who has XML where they seem to want an array of inventory, but with each item listed after the other with no wrapping node.
Here is an example of what I'm doing, but with a wrapping node for each item. Is there a way to do it so that they are just all listed one after the other under "root"?
Test code:
package main
import (
"encoding/xml"
"fmt"
"os"
"strconv"
)
func main() {
type InventoryItem struct {
XMLName xml.Name
ItemName string `xml:"Name"`
ItemDescription string `xml:"Description"`
}
type XMLEnvelop struct {
XMLName xml.Name `xml:"root"`
Inventory []InventoryItem `xml:"item"`
Records int `xml:"records"`
}
var items []InventoryItem
for i := 1; i < 6; i++ {
items = append(items, InventoryItem{XMLName: xml.Name{Local: "item" + strconv.Itoa(i)}, ItemName: "Test " + strconv.Itoa(i), ItemDescription: "Description " + strconv.Itoa(i)})
}
v := &XMLEnvelop{Records: 1, Inventory: items}
output, err := xml.MarshalIndent(v, "", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
// Write the output to check
os.Stdout.Write(output)
//Here is where I would make the request
}
Test Output:
<root>
<item1>
<Name>Test 1</Name>
<Description>Description 1</Description>
</item1>
<item2>
<Name>Test 2</Name>
<Description>Description 2</Description>
</item2>
<item3>
<Name>Test 3</Name>
<Description>Description 3</Description>
</item3>
<item4>
<Name>Test 4</Name>
<Description>Description 4</Description>
</item4>
<item5>
<Name>Test 5</Name>
<Description>Description 5</Description>
</item5>
<records>1</records>
</root>
Go Playground: https://play.golang.org/p/3DRUaBFEQvC
This is the output that they seem to be looking for...for whatever reason.
<root>
<Name>Test 1</Name>
<Description>Description 1</Description>
<Name>Test 2</Name>
<Description>Description 2</Description>
<Name>Test 3</Name>
<Description>Description 3</Description>
<Name>Test 4</Name>
<Description>Description 4</Description>
<Name>Test 5</Name>
<Description>Description 5</Description>
<records>1</records>
</root>
答案1
得分: 1
你可以实现一个自定义的编组器。
type InventoryItem struct {
XMLName xml.Name
ItemName string `xml:"Name"`
ItemDescription string `xml:"Description"`
}
func (i InventoryItem) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
// 忽略传入的 `start` 参数,它表示 Name 和 Description 的父级 InventoryItem 元素。
// 声明类型来表示要编码的元素,将它们初始化为项的字段值并进行编码。
//
// 使用 ",chardata" 选项告诉编码器直接编码字段的值,而不是作为子元素。
type Name struct {
Value string `xml:",chardata"`
}
if err := e.Encode(Name{i.ItemName}); err != nil {
return err
}
type Description struct {
Value string `xml:",chardata"`
}
return e.Encode(Description{i.ItemDescription})
}
https://play.golang.org/p/D4ZVr2sWZju
英文:
You can implement a custom marshaler.
type InventoryItem struct {
XMLName xml.Name
ItemName string `xml:"Name"`
ItemDescription string `xml:"Description"`
}
func (i InventoryItem) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
// Ignore the passed in `start` argument, it represents the
// parent InventoryItem element of the Name and Description.
// Declare types to represent the elements you want to encode,
// initialize them to the item's field values and encode them.
//
// Use the ",chardata" option to tell the encoder to encode the
// field's value directly rather than as a child element.
type Name struct {
Value string `xml:",chardata"`
}
if err := e.Encode(Name{i.ItemName}); err != nil {
return err
}
type Description struct {
Value string `xml:",chardata"`
}
return e.Encode(Description{i.ItemDescription})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论