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

Incorrectly generated code for `mixed="true"` complex types #74

Open halostatue opened 5 months ago

halostatue commented 5 months ago

Description

If a complexType is defined with mixed="true", it should collect the innerXml or CDATA in addition to the tags. The examples in this ticket are generated using the SFCC catalog.xsd which also requires the xml.xsd file from https://salesforcecommercecloud.github.io/b2c-dev-doc/docs/current/xsd/.

Inside of it, the following types are declared:

    <xsd:complexType name="sharedType.CustomAttributes" mixed="false">
        <xsd:sequence>
            <xsd:element name="custom-attribute" type="sharedType.CustomAttribute" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="sharedType.CustomAttribute" mixed="true">
        <xsd:sequence>
            <xsd:element name="value" type="simpleType.Generic.String" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="attribute-id" type="simpleType.Generic.NonEmptyString.256" use="required" />
        <xsd:attribute ref="xml:lang" />
    </xsd:complexType>

This generates the following Go code:

// SharedTypeCustomAttributes ...
type SharedTypeCustomAttributes struct {
    XMLName         xml.Name                     `xml:"sharedType.CustomAttributes"`
    Customattribute []*SharedTypeCustomAttribute `xml:"custom-attribute"`
}

// SharedTypeCustomAttribute ...
type SharedTypeCustomAttribute struct {
    XMLName         xml.Name `xml:"sharedType.CustomAttribute"`
    AttributeidAttr string   `xml:"attribute-id,attr"`
    XmlLangAttr     string   `xml:"xml:lang,attr,omitempty"`
    Value           []string `xml:"value"`
}

In most cases from SFCC files, this is presented as <custom-attribute attribute-id="foo">bar</custom-attribute>, and using xgen there's no way to get access to the bare contents of the optional <value/> tag.

Steps to reproduce the issue:

  1. Use the XSD files mentioned above.
  2. Run xgen -i catalog.xsd -l Go -o tmp/catalog

Describe the results you received:

Note that there's no way of getting the inner XML, only Value[].

Describe the results you expected:

A way to get the inner XML in addition to Value[].

Output of go version:

go version go1.22.3 darwin/arm64

xgen version or commit ID:

0.1.0

Environment details (OS, physical, etc.):

macOS 14.5

halostatue commented 5 months ago

Note that GoComply/xsd2go generates this correctly. If xgen were to generate this correctly, there would be another issue for xsd:extends where the parent type has mixed="true" and the child type has mixed="false" or unspecified. Specifically, xgen makes the choice to generate the following code for such an entry:

// SharedTypeCustomAttributes ...
type SharedTypeCustomAttributes struct {
    XMLName         xml.Name                     `xml:"sharedType.CustomAttributes"`
    Customattribute []*SharedTypeCustomAttribute `xml:"custom-attribute"`
}

// SharedTypeCustomAttribute ...
type SharedTypeCustomAttribute struct {
    XMLName         xml.Name `xml:"sharedType.CustomAttribute"`
    AttributeidAttr string   `xml:"attribute-id,attr"`
    XmlLangAttr     string   `xml:"xml:lang,attr,omitempty"`
    Value           []string `xml:"value"`
}

// SharedTypeSiteSpecificCustomAttributes ...
type SharedTypeSiteSpecificCustomAttributes struct {
    XMLName         xml.Name                                 `xml:"sharedType.SiteSpecificCustomAttributes"`
    Customattribute []*SharedTypeSiteSpecificCustomAttribute `xml:"custom-attribute"`
}

// SharedTypeSiteSpecificCustomAttribute ...
type SharedTypeSiteSpecificCustomAttribute struct {
    XMLName    xml.Name `xml:"sharedType.SiteSpecificCustomAttribute"`
    SiteidAttr string   `xml:"site-id,attr,omitempty"`
    *SharedTypeCustomAttribute
}

If SharedTypeCustomAttribute gets InnerXml generated, then SharedTypeSiteSpecificCustomAttribute will also implicitly get InnerXml through the embedding. This is something not well defined in the XSD specification, but that discussions from 2005 on the XSD mailing list and 2012 on StackOverflow strongly suggest that the mixed attribute is not inherited. That means that SharedTypeSiteSpecificCustomAttribute would need to be implemented separately and not via embedded inheritance since the mixed attribute differs (or, more specifically, that mixed=false is stricter than mixed=true). (The optimization could be kept if the mixed attributes matched, and I believe that there is a bug in the SFCC impex XSD which I have reported into the SFCC black hole.)