T
T
triopsidae2019-05-02 17:33:08
go
triopsidae, 2019-05-02 17:33:08

How to parse XML to JSON?

Good afternoon, there is an XML file:

<profile>
    <profile_name>Profile 1</profile_name>
    <field>
        <name>role</name>
        <type>string</type>
        <value>user</value>
    </field>
    <field>
        <name>age</name>
        <type>int</type>
        <value>30</value>
    </field>
</profile>
<profile>
    <profile_name>Profile 2</profile_name>
    <field>
        <name>role</name>
        <type>string</type>
        <value>user</value>
    </field>
    <field>
        <name>age</name>
        <type>int</type>
        <value>30</value>
    </field>
</profile>
<profile>
    <profile_name>Profile 3</profile_name>
    <field>
        <name>role</name>
        <type>string</type>
        <value>admin</value>
    </field>
</profile>

It needs to be parsed into a JSON file to get the following result:
{
    "Profile 1": {
        "role": "user",
        "age": 30
    },
    "Profile 2": {
        "role": "user",
        "age": 30
    },
    "Profile 3": {
        "role": "admin"
    }
}

Here is a code snippet that parses the given XML file:
type XMLProfile struct {
  XMLName     xml.Name    `xml:"profile,omitempty"`
  ProfileName string      `xml:"profile_name",omitempty`
  Fields      []*XMLField `xml:"field,omitempty"`
}

type XMLField struct {
  Name  string `xml:"name,omitempty"`
  Type  string `xml:"type,omitempty"`
  Value string `xml:"value,omitempty"`
}

func main() {
  file, err := os.Open("example.xml")
  if err != nil {
    log.Println(err)
  }

  defer file.Close()

  decoder := xml.NewDecoder(file)
  for {
    t, _ := decoder.Token()
    if t == nil {
      break
    }

    switch et := t.(type) {
    case xml.StartElement:
      if et.Name.Local == "profile" {
        var object XMLProfile
        decoder.DecodeElement(&object, &et)

        resultData := map[string]map[string]string{
          object.ProfileName: map[string]string{},
        }

        for _, val := range object.Fields {
          resultData[object.ProfileName][val.Name] = val.Value
        }
        if out, err := json.MarshalIndent(resultData, "", " "); err != nil {
          panic(err)
        } else {
          _ = ioutil.WriteFile("test.json", out, 0644)
        }
      }
    }
  }
}

And the result:
{
 "Profile 3": {
  "role": "admin"
 }
}

How to correctly parse the given XML into JSON so that the correct result would come out?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Sinu5oid, 2019-11-29
@Sinu5oid

Although a necropost, I will still give an answer
There is a typo in the type description

type XMLProfile struct {
  XMLName     xml.Name    `xml:"profile,omitempty"`
  ProfileName string      `xml:"profile_name",omitempty`
  Fields      []*XMLField `xml:"field,omitempty"`
}

Specifically here: `xml:"profile_name ",omitempty `
Go does not allow mistakes in the meta-information of structures, here is the correct option:
`xml:"profile_name ,omitempty" ` - first backtic, then without spaces: data type label (xml), colon, quotation marks, name in xml, comma, additional tags, quotation marks (if you need to set a description for json as well, put a space, repeat the same thing), at the end again backtick
That's the whole fix :)
Final code:
package main

import (
  "encoding/json"
  "encoding/xml"
  "io/ioutil"
  "log"
  "os"
)

type XMLProfile struct {
  XMLName     xml.Name    `xml:"profile,omitempty"`
  ProfileName string      `xml:"profile_name,omitempty"`
  Fields      []*XMLField `xml:"field,omitempty"`
}

type XMLField struct {
  Name  string `xml:"name,omitempty"`
  Type  string `xml:"type,omitempty"`
  Value string `xml:"value,omitempty"`
}

func main() {
  file, err := os.Open("example.xml")
  if err != nil {
    log.Println(err)
  }

  defer file.Close()

  decoder := xml.NewDecoder(file)
  for {
    t, _ := decoder.Token()
    if t == nil {
      break
    }

    switch et := t.(type) {
    case xml.StartElement:
      if et.Name.Local == "profile" {
        var object XMLProfile
        decoder.DecodeElement(&object, &et)

        resultData := map[string]map[string]string{
          object.ProfileName: map[string]string{},
        }

        for _, val := range object.Fields {
          resultData[object.ProfileName][val.Name] = val.Value
        }
        if out, err := json.MarshalIndent(resultData, "", " "); err != nil {
          panic(err)
        } else {
          _ = ioutil.WriteFile("test.json", out, 0644)
        }
      }
    }
  }
}

A
Artyom Bolotov, 2019-05-02
@NoSure

Intrigued...
www.cihanozhan.com/converting-xml-data-to-json-wit...
or
How to parse XML in Go?
finish a little and it will be the most

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question