golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.7k stars 17.5k forks source link

proposal: encoding/xml: support marshal self-closing tag in short-form mode #59710

Open ECUST-XX opened 1 year ago

ECUST-XX commented 1 year ago

Goals

Add an option, to support marshal a self-closing tag xml struct in short-form mode which has empty content.

In xml standard, a self-closing tag is permitted. https://www.w3.org/TR/xml/#sec-starttags

Definitions

func ExampleMarshalShortForm() {
    type Address struct {
        City, State string
    }
    type Person struct {
        XMLName   xml.Name `xml:"person"`
        Id        int      `xml:"id,attr"`
        FirstName string   `xml:"name>first"`
        LastName  string   `xml:"name>last"`
        Age       int      `xml:"age"`
        Height    float32  `xml:"height,omitempty"`
        Married   bool
        Address
        Comment       string   `xml:",comment"`
        FavoriteMusic []string `xml:"favorite_music"`
        LuckyNumber   int      `xml:"lucky_number"`
    }

    v := &Person{Id: 13, FirstName: "John", LastName: ""}
    v.Comment = " Need more details. "
    v.Address = Address{"Hanga Roa", ""}
    v.FavoriteMusic = []string{"Made in Heaven", ""}

    output, err := xml.MarshalIndentShortForm(v, "  ", "    ")
    if err != nil {
        fmt.Printf("error: %v\n", err)
    }

    os.Stdout.Write(output)
    // Output:
    //   <person id="13">
    //       <name>
    //           <first>John</first>
    //           <last />
    //       </name>
    //       <age>0</age>
    //       <Married>false</Married>
    //       <City>Hanga Roa</City>
    //       <State />
    //       <!-- Need more details. -->
    //       <favorite_music>Made in Heaven</favorite_music>
    //       <favorite_music />
    //       <lucky_number>0</lucky_number>
    //   </person>
}

Related questions

#21399

ianlancetaylor commented 1 year ago

Just to be clear, I think you are proposing a new function MarshalIndentShortForm. That will be like MarshalIndent, but a tag with no contents will use a self-closing tag. Is that about right?

ECUST-XX commented 1 year ago

Just to be clear, I think you are proposing a new function MarshalIndentShortForm. That will be like MarshalIndent, but a tag with no contents will use a self-closing tag. Is that about right?

Yes. That's right.

adonovan commented 1 year ago

What is the cost of using a self-closing tag wherever it is allowed?

tnypxl commented 11 months ago

@adonovan Cost in terms of what? Can you elaborate?

adonovan commented 11 months ago

tnypxl: Cost in terms of what? Can you elaborate?

I meant all kinds of costs. Obviously any change has the potential to cause spurious failures in existing overly-specific tests, but are there more substantial reasons why not to simply enable it always? The output would be more compact, which seems like a good thing.

tnypxl commented 11 months ago

@adonovan Thanks for the clarification. I do agree with your last point. I am running into this issue while researching ways to build a XML config generator.

Without having looked into the current std lib implemtantion, I imagine an always-on approach would break some tests that expect a closing tag from empty elements. I'd be interested in a struct field tag option (e.g, closeempty or selfclose) that lets me decide on a field by field basis. But I imagine for large complex XML trees, that isn't ideal either.

ydnar commented 10 months ago

We have a small change that implements the selfclosing option to the xml struct tag here:

https://github.com/nbio/xml/pull/10

Happy to turn this into a formal proposal + CL if folks are interested.

msurmeli commented 5 months ago

Having a field based struct tag would allow us to decide whether to use self closing tags per field. Personally I would prefer to see your approach as proposal. @ydnar

ianlancetaylor commented 2 days ago

See https://github.com/golang/go/issues/69273 for an alternate proposal.