Home > Blockchain >  Array of struct in XML with no wrapping node?
Array of struct in XML with no wrapping node?

Time:11-07

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})
}

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

  • Related