Write the XML to an XML file in Go

I have a script for this print string XML code, but I need it to write a new XML file and then write the XML code to the file instead of printing it. A.

Here is the function that prints the XML code

func processTopic(id string, properties map[string][]string) {
    fmt.Printf("<card entity=\"%s\">\n", id)
    fmt.Println("  <facts>")
    for k, v := range properties {
        for _,value := range v {
            fmt.Printf("    <fact property=\"%s\">%s</fact>\n", k, value)
        }
    }
    fmt.Println("  </facts>")
    fmt.Println("</card>")
}

How can I get him to write an XML file and then write code to this XML file?

+4
source share
4 answers

To add the correct answer to bgp (+1); changing the function to use the io.Writer parameter as an argument, you can output your XML to any type of output by implementing the io.Writer interface .

func processTopic(w io.Writer, id string, properties map[string][]string) {
    fmt.Fprintf(w, "<card entity=\"%s\">\n", id)
    fmt.Fprintln(w, "  <facts>")
    for k, v := range properties {
        for _,value := range v {
            fmt.Fprintf(w, "    <fact property=\"%s\">%s</fact>\n", k, value)
        }
    }
    fmt.Fprintln(w, "  </facts>")
    fmt.Fprintln(w, "</card>")
}

Screen printing (Stdout):

processTopic(os.Stdout, id, properties)

Writing to a file (code taken from bgp answer):

f, err := os.Create("out.xml") // create/truncate the file
if err != nil { panic(err) } // panic if error
defer f.Close() // make sure it gets closed after
processTopic(f, id, properties)
+2
source

XML , encoding/xml? XML:

type Card struct {
    Entity string `xml:"entity,attr"`
    Facts  Facts
}

type Facts struct {
    Fact []Fact
}

type Fact struct {
    Property string `xml:"property,attr"`
    Value string `xml:",innerxml"`
}

( ):

card := &Card{
    Entity: "1234id",
    Facts: Facts{[]Fact{
        Fact{Property: "prop1", Value: "val1"},
        Fact{Property: "prop2", Value: "val2"},
    }},
}

XML io.Writer:

writer, err := os.Open("/tmp/tmp.xml")

encoder := xml.NewEncoder(writer)
err := encoder.Encode(data)

if err != nil { panic(err) }
+13

os.Create, fmt.Fprintf, .

:

f, err := os.Create("out.xml") // create/truncate the file
if err != nil { panic(err) } // panic if error
defer f.Close() // make sure it gets closed after

fmt.Fprintf(f, "<card entity=\"%s\">\n", id)
// ...
+3

nemo encoding/xml; , fact, map[string]string, Unmarshaler fact. , , , ( /).

package main

import (
    "encoding/xml"
    "io"
    "os"
)

type FactMap map[string]string

type factXml struct {
    XMLName xml.Name `xml:"fact"`
    Prop string `xml:"property,attr"`
    Value string `xml:",innerxml"`
}

// Marshal the fact map
func (fm FactMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    if len(fm) == 0 {
        return nil
    }

    err := e.EncodeToken(start)
    if err != nil {
        return err
    }

    for k, v := range fm {
        // XML encoding the `fact` XML entry
        e.Encode(factXml{Prop: k, Value: v})
    }

    return e.EncodeToken(start.End())
}

// Unmarshal the fact map
func (fm *FactMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    *fm = FactMap{}
    for {
        var f factXml

        err := d.Decode(&f)
        if err == io.EOF {
            break
        } else if err != nil {
            return err
        }

        (*fm)[f.Prop] = f.Value
    }
    return nil
}

// Note usage of xml.Name to set the outer XML to `card`, as well as setting Entity as an `entity,attr`
type Card struct {
    XMLName xml.Name `xml:"card"`
    Entity int `xml:"entity,attr"`
    Facts FactMap `xml:"facts"`
}

func main() {
    props1 := map[string]string{"key1": "val1", "key2": "val2"}

    // Populate the Card struct and marshal it
    card := Card{Entity: 5, Facts: props1}

    // Append to the file
    var f *os.File

    // Check if thet file exists, err != nil if the file does not exist
    _, err := os.Stat("my.xml")
    if err != nil {
        // if the file doesn't exist, open it with write and create flags
        f, err = os.OpenFile("my.xml", os.O_WRONLY|os.O_CREATE, 0666)
    } else {
        // if the file does exist, open it with append and write flags
        f, err = os.OpenFile("my.xml", os.O_APPEND|os.O_WRONLY, 0666)
    }
    if err != nil {
        panic(err)
    }
    defer f.Close()

    e := xml.NewEncoder(f)

    // Write marshal the card struct to the file
    err = e.Encode(card)
    if err != nil {
        panic(err)
    }
}
0

All Articles