xuri / xgen

XSD (XML Schema Definition) parser and Go/C/Java/Rust/TypeScript code generator
BSD 3-Clause "New" or "Revised" License
339 stars 80 forks source link

xsd:group generates incorrect output in Go #33

Open mark-edgeworth opened 3 years ago

mark-edgeworth commented 3 years ago

Description

When a complex type contains an xsd:group reference, the generated code produces a new struct type for the group rather than expanding the group content in the original type. Also, no xml:"..." mapping code is generated, so the group is not parsed from the XML.

I'd prefer it that the group did not yield a new type (as it is just syntactic sugar inside the schema rather than a real hierarchical component).

Steps to reproduce the issue: Using the following test schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified" version="0.0.1">
    <!-- Device Properties Group -->
    <xs:group name="MyGroup">
        <xs:sequence>
            <!-- A couple of test elements -->
            <xs:element name="element_1"  type="xs:string"/>
            <xs:element name="element_2" type="xs:string"/>
        </xs:sequence>
    </xs:group>

    <xs:element name="parent_element">
        <xs:complexType>
            <xs:group ref="MyGroup" />
            <xs:attribute name="attr_1" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>

</xs:schema>

Describe the results you received:

Generated code is

// Code generated by xgen. DO NOT EDIT.

package schema

import (
    "encoding/xml"
)

// MyGroup ...
type MyGroup struct {
    Element1 string
    Element2 string
}

// Parentelement ...
type Parentelement struct {
    XMLName   xml.Name `xml:"parent_element"`
    Attr1Attr string   `xml:"attr_1,attr"`
    MyGroup   *MyGroup
}

Describe the results you expected: Something like:

// Code generated by xgen. DO NOT EDIT.

package schema

import (
    "encoding/xml"
)

// Parentelement ...
type Parentelement struct {
    XMLName   xml.Name `xml:"parent_element"`
    Attr1Attr string   `xml:"attr_1,attr"`
    Element1 string `xml:"element_1"`
    Element2 string `xml:"element_2"`
}

Output of go version:

go version go1.16.6 darwin/amd64

xgen version or commit ID:

v0.1.0

Environment details (OS, physical, etc.): MacOS 11.6 Big Sur on Mac Book Pro

zadeck commented 2 years ago

I think that the problem is more subtle than this and that the proper solution is not to inline the group. Consider the following xsd schemata:

<?xml version="1.0" encoding="UTF-8"?>

====== xgen generated the following incorrect code: ====== // Code generated by xgen. DO NOT EDIT. package test2 import ( "encoding/xml" ) // E ... type E struct { XMLName xml.Name `xml:"e"` Foo1 *Foo1 Foo2 *Foo2 } // Foo ... type Foo struct { XMLName xml.Name `xml:"foo"` NameAttr string `xml:"name,attr"` Value1Attr float64 `xml:"value1,attr"` } ======= What I think that it really should have done is to use the group name as the name of the structure but put the element name in the attribute for the XMLName. ======= // Code generated by xgen. DO NOT EDIT. package test2 import ( "encoding/xml" ) // E ... type E struct { XMLName xml.Name `xml:"e"` Foo1 *Foo1 Foo2 *Foo2 } // Foo1 ... type Foo1 struct { XMLName xml.Name `xml:"foo"` NameAttr string `xml:"name,attr"` Value1Attr float64 `xml:"value1,attr"` } // Foo2 ... type Foo2 struct { XMLName xml.Name `xml:"foo"` NameAttr string `xml:"name,attr"` Value1Attr int `xml:"value1,attr"` } ====== The problem with inlining the group is that if it is referenced many times, you can get a big expansion.