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>
CodePudding user response:
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})
}