0

I have an example that I'm attempting to parse. I'm able to get the <Documents> but cannot get <ChangeOrders>. I've combined what I've seen in a few other questions on the site here, specifically these: Unmarshaling XML in Go, golang xml Unmarshal, Golang XML parse

Below is what I've written so far:

package main

import (
    "bytes"
    "encoding/json"
    "encoding/xml"
    "fmt"
    "log"
)

type AgileData struct {
    Documents   []Document  `xml: "AgileData>Documents"`
    ChangeOrder ChangeOrder `xml: "AgileData>ChangeOrders"`
}

type ChangeOrder struct {
    CoverPage CoverPage `xml:"CoverPage"`
}

type CoverPage struct {
    Number string `xml:"Number"`
}

type Document struct {
    TitleBlock  TitleBlock    `xml:"TitleBlock"`
    Attachments []Attachments `xml:"Attachments"`
}

type TitleBlock struct {
    Number          string `xml:"Number"`
    LifecyclePhase  string `xml:"LifecyclePhase"`
    Rev             string `xml:"Rev"`
    EffectivityDate string `xml:"EffectivityDate"`
}

type Attachments struct {
    FileName string `xml:"FileName"`
    EFD      string `xml:"List01"`
}

func main() {
    agile_xml := `
        <AgileData xmlns="http://www.oracle.com/webfolder/technetwork/xml/plm/2016/09/" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xsi:schemaLocation="http://www.oracle.com/webfolder/technetwork/xml/plm/2016/09/ http://www.oracle.com/webfolder/technetwork/xml/plm/2016/09/aXML.xsd">
            <ChangeOrders>
                <CoverPage>
                    <Number>C0000001</Number>
                </CoverPage>
            </ChangeOrders>
            <Documents>
                <TitleBlock>
                    <Number>D00000001</Number>
                    <LifecyclePhase>Published</LifecyclePhase>
                    <Rev>001    C00000001</Rev>
                </TitleBlock>
                <Attachments>
                    <FileName>some-file.docx</FileName>
                    <List01>PDF with banners</List01>
                </Attachments>
            </Documents>
            <Documents>
                <TitleBlock>
                    <Number>D00000002</Number>
                    <LifecyclePhase>Published</LifecyclePhase>
                    <Rev>001    C00000001</Rev>
                </TitleBlock>
                <Attachments>
                    <FileName>some-other-file.docx</FileName>
                    <List01>No distribution</List01>
                </Attachments>
            </Documents>
        </AgileData>
    `

    xmlReader := bytes.NewReader([]byte(agile_xml))
    yourAgileData := new(AgileData)
    if err := xml.NewDecoder(xmlReader).Decode(yourAgileData); err != nil {
        log.Panic(err.Error())
    }

    printX(yourAgileData)
}

func printX(x interface{}) (err error) {
    var xBytes []byte
    xBytes, err = json.MarshalIndent(x, "", "  ")
    if err != nil {
        return
    }
    fmt.Println(string(xBytes))
    return
}

Go playground link

If you run this, I get back data in Documents[], but ChangeOrder is blank. I'm not sure what I've missed.

"ChangeOrder": {
    "CoverPage": {
      "Number": ""
    }
  }

Extra question: Why does go vet complain about these lines?

    Documents   []Document  `xml: "AgileData>Documents"`
    ChangeOrder ChangeOrder `xml: "AgileData>ChangeOrders"`

If I remove the space between "xml:" and "AgileData..", the warning goes away but then the Documents[] array starts to return empty.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189

1 Answers1

1

Remove the root level tag:

    Documents   []Document  `xml:"Documents"`
    ChangeOrder ChangeOrder `xml:"ChangeOrders"`

The XML decoder assumes that the document element corresponds to the struct you're decoding it to. So the actual XML element/struct field matching starts under the document element.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59