Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xsdgen: issues with wildcards & embedded fields #31

Closed
droyo opened this issue Oct 16, 2017 · 2 comments
Closed

xsdgen: issues with wildcards & embedded fields #31

droyo opened this issue Oct 16, 2017 · 2 comments
Labels

Comments

@droyo
Copy link
Owner

droyo commented Oct 16, 2017

The dash branch contains the DASH-MPD XSD and sample data in the gentest directory.

Currently the tests fail due to an invalid marshalling of the SegmentList element. It is supposed to generate something like this:

	<SegmentList timescale="90000" duration="5400000">
	  <RepresentationIndex sourceURL="representation-index.sidx">
	  </RepresentationIndex>
	  <SegmentURL media="segment-1.ts">
	  </SegmentURL>
	  ...
	</SegmentList>

Instead we get this:

	<SegmentList timescale="90000" xmlns="urn:mpeg:dash:schema:mpd:2011">
	  <Items>
	  </Items>
	  <Items>
	  </Items>
	  ...
	</SegmentList>

This is due to the <SegmentURL> items being unmarshalled into the wrong place. Here's the the relevant type declarations:

type SegmentListType struct {
	MultipleSegmentBaseType
	Actuate    ActuateType      `xml:"actuate,attr,omitempty"`
	SegmentURL []SegmentURLType `xml:"urn:mpeg:dash:schema:mpd:2011 SegmentURL,omitempty"`
}

Within MultipleSegmentBaseType is the following:

Items                    []string `xml:",any"`

This feels like a possible bug, or at least, unexpected behavior in the encoding/xml package; it is dropping the SegmentURL items into this wildcard field, even though further down SegmentListType there is a more specific field matching those items. This is probably due to the fact that the wildcard field is in an embedded type.

@droyo
Copy link
Owner Author

droyo commented Oct 17, 2017

Looking into this further, I believe I've found the issue. With the commit ed9a5b5, I used something like the following strategy to override unmarshalling for individual fields in a struct:

type T RealType
var overlay struct {
	*T
	AvailabilityStartTime *xsdDateTime `xml:"availabilityStartTime,attr,omitempty"`
}
overlay.T = (*T)(t)
overlay.AvailabilityStartTime = (*xsdDateTime)(&layout.T.AvailabilityStartTime)
return d.DecodeElement(&overlay, &start)

Notably, the local type T is used to "silence" the MarshalXML method of RealType. This lets us use all the convenient reflection in the encoding/xml package while only having to override the fields we want. Now look at this example program:

https://play.golang.org/p/0el2d1S145

In short, methods of the embedded structs are not silenced by the type T trick. As a result, in the example above, if RealType had an embedded field that had its own UnmarshalXML implementation, that method would be called instead of falling through to encoding/xml's built-in unmarshalling logic.

So, the workaround here would be to forgo struct embedding, and expand the base type that a complexType extends. The internal/dependency package could be useful here for "dereferencing" types in the correct order.

This will make the generated files larger for complex schema, and make the type hierarchy less obvious. However, I don't see a better alternative.

@droyo
Copy link
Owner Author

droyo commented Oct 20, 2017

Fixed with b12a23a

@droyo droyo closed this as completed Oct 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant