Golang: Tags for immediate closure

So, I'm trying a Unmarshal XML file generated as a save file by another program in Google Go. This seems like good, as the documentation on this is quite extensive: http://golang.org/pkg/encoding/xml/#Unmarshal

Still, I have a problem. The result in the save file is as follows:

<location id="id4" x="-736" y="-544">
    <committed />
</location>

Instead of a fixed location, it may be urgent or not. Places may also have a name and different labels, but they seem to be well-understood. In my Go code, I use the following structure:

type Location struct {
    Id string `xml:"id,attr"`
    Committed bool `xml:"commited"`
    Urgent bool `xml:"urgent"`
    Labels []Label `xml:"label"`
}

And although the Unmarshal function of the encoding / xml package works without errors, and the example shown is present in the data, all values โ€‹โ€‹of both fixed and urgent are "false".

, ?

(Unmarshalling )

xmlFile, err := os.Open("model.xml")
if err != nil {
    fmt.Println("Error opening file:", err)
    return
}
defer xmlFile.Close()

b, _ := ioutil.ReadAll(xmlFile)

var xmlScheme uppaal.UppaalXML
err = xml.Unmarshal(b, &xmlScheme)
fmt.Println(err)
+4
3

, , , , committed . , , ( ) ( ).

golang-nuts rsc *struct{} ( ) , nil ( ):

type Location struct {
    Id        string    `xml:"id,attr"`
    Committed *struct{} `xml:"committed"`
    Urgent    bool      `xml:"urgent"`
}

if l.Committed != nil {
    // handle not committed
}
+8

, , , :

XML:

<struct>
    <hide/>
    <data>Value</data>
</struct>

Go:

type XMLValues struct {
    Hide BoolIfElementPresent `xml:"hide"`
    Data string               `xml:"data"`
}

type BoolIfElementPresent struct {
    bool
}

func (c *BoolIfElementPresent) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    var v string
    d.DecodeElement(&v, &start)
    *c = BoolIfElementPresent{true}
    return nil
}

, , <hide/> , unmarshalling , true. <hide/> , , false .

, , .

d.DecodeElement(&v, &start) , , :

xml: (* mypackage.BoolIfElementPresent).UnmarshalXML

: @ShogunPanda:

type XMLValues struct {
    Hide BoolIfElementPresent `xml:"hide"`
    Data string               `xml:"data"`
}

type BoolIfElementPresent bool

func (c *BoolIfElementPresent) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    var v string
    d.DecodeElement(&v, &start)
    *c = true
    return nil
}

, if xyz == true.

+2

An easy way to solve this problem of empty self-launch tags or an empty tag is to use https://github.com/guregu/null .

I'm not a big fan of using packages for little things, but this package has saved a lot of time for me.

This is how i use this

package main

import (
    "encoding/xml"
    "fmt"

    "github.com/guregu/null"
)

func main() {
    type Result struct {
        XMLName xml.Name   `xml:"Person"`
        Name    string     `xml:"FullName"`
        Id      null.Int   `xml:"Id"`
        Height  null.Float `xml:"Height"`
    }
    v := Result{}

    data := `
        <Person>
            <FullName>Grace R. Emlin</FullName>
            <Id></Id>
            <Height />
        </Person>
    `
    err := xml.Unmarshal([]byte(data), &v)

    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }

    fmt.Printf("XMLName: %#v\n", v.XMLName)
    fmt.Printf("Name: %q\n", v.Name)

    if !v.Id.IsZero() {
        fmt.Printf("Id: %d\n", v.Id.Int64)
    }
}

http://play.golang.org/p/xGKeIUM6NO

Full credit for guregu / null

0
source

Source: https://habr.com/ru/post/1541034/


All Articles