I am trying to unmarshal some XML, actually Geography Markup Language (GML).
I have an example at http://play.golang.org/p/qS6GjCOtHF
Two problems, the first:
error reading xml main.FeatureCollection field "LowerCorner" with tag "boundedBy>Envelope>lowerCorner" conflicts with field "Envelope" with tag "boundedBy>Envelope"
I have no idea how to fix that. I commented those out and get the GML to unmarshal without errors but then there are no Features
in the FeatureCollection
.
Any clues?
An example of the GML is:
<?xml version="1.0" encoding="UTF-8"?>
<gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fme="http://www.safe.com/gml/fme" xsi:schemaLocation="http://www.safe.com/gml/fme tblMainGML.xsd">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:3112" srsDimension="2">
<gml:lowerCorner>45.2921142578125 -80.2166748046875</gml:lowerCorner>
<gml:upperCorner>169.000122070313 -9.14251708984375</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<gml:featureMember>
<fme:GML gml:id="id5255fa48-42b3-43d1-9e0d-b2ba8b57a936">
<fme:OBJECTID>1</fme:OBJECTID>
<fme:RECORD_ID>QLD48234</fme:RECORD_ID>
<fme:NAME>HATCHMAN POINT</fme:NAME>
<fme:FEAT_CODE>PT</fme:FEAT_CODE>
<fme:CGDN>N</fme:CGDN>
<fme:AUTHORITY_ID>QLD</fme:AUTHORITY_ID>
<fme:CONCISE_GAZ>N</fme:CONCISE_GAZ>
<fme:LATITUDE>-12.58361</fme:LATITUDE>
<fme:lat_degrees>-12</fme:lat_degrees>
<fme:lat_minutes>35</fme:lat_minutes>
<fme:lat_seconds>0</fme:lat_seconds>
<fme:LONGITUDE>141.62583</fme:LONGITUDE>
<fme:long_degrees>141</fme:long_degrees>
<fme:long_minutes>37</fme:long_minutes>
<fme:long_seconds>32</fme:long_seconds>
<fme:STATE_ID>QLD</fme:STATE_ID>
<fme:STATUS>U</fme:STATUS>
<fme:VARIANT_NAME />
<fme:MAP_100K>7272</fme:MAP_100K>
<fme:Place_ID>45880</fme:Place_ID>
<gml:pointProperty>
<gml:Point srsName="EPSG:3112" srsDimension="2">
<gml:pos>141.625915527344 -12.5836181640625</gml:pos>
</gml:Point>
</gml:pointProperty>
</fme:GML>
</gml:featureMember>
</gml:FeatureCollection>
</xml>
My structs
type FeatureCollection struct {
Xsi string `xml:"xsi,attr"`
Fme string `xml:"fme,attr"`
Gml string `xml:"gml,attr"`
Xlink string `xml:"xlink,attr"`
LowerCorner string `xml:"boundedBy>Envelope>lowerCorner"`
UpperCorner string `xml:"boundedBy>Envelope>upperCorner"`
Envelope Envelope `xml:"boundedBy>Envelope"`
SchemaLocation string `xml:"schemaLocation,attr"`
Features []Feature
}
type Feature struct {
PlaceID string `xml:"featureMember>GML>Place_ID"`
StateID string `xml:"featureMember>GML>STATE_ID"`
Postcode string `xml:"featureMember>GML>POSTCODE"`
CGDN string `xml:"featureMember>GML>CGDN"`
Map100K string `xml:"featureMember>GML>MAP_100K"`
ETC...
}
An XML tag can only be mapped to (at most) one struct field. The encoding/xml
package has to decide for each XML tag into which struct field it will be decoded. Your structs that model the XML are weird, and make this decision ambiguous.
For example let's take this example:
type FeatureCollection struct {
...
LowerCorner string `xml:"boundedBy>Envelope>lowerCorner"`
UpperCorner string `xml:"boundedBy>Envelope>upperCorner"`
Envelope Envelope `xml:"boundedBy>Envelope"`
...
}
The encoding/xml
package can't decide where the XML tag <Envelope>
should be decoded into, e.g. into LowerCorner
? into UpperCorner
? into Envelope
? Yes, I know LowerCorner
is only a sub-element of <Envelope>
but since the whole <Envelope>
element is mapped to FeatureCollection.Envelope
, this is not allowed.
You should move LowerCorner
and UpperCorner
fields into your Envelope
struct type because that's where they belong to and you want to unmarshal the whole Envelope
xml tag (or if not, FeatureCollection.Envelope
could be removed entirely). So follow this pattern to put fields to where they belong.
Here is your updated model which extracts all the info you wanted:
type FeatureCollection struct {
Xsi string `xml:"xsi,attr"`
Fme string `xml:"fme,attr"`
Gml string `xml:"gml,attr"`
Xlink string `xml:"xlink,attr"`
Envelope Envelope `xml:"boundedBy>Envelope"`
SchemaLocation string `xml:"schemaLocation,attr"`
FeaturesGML []GML `xml:"featureMember>GML"`
}
type Envelope struct {
SrsName string `xml:"srsName,attr"`
SrsDimension string `xml:"srsDimension,attr"`
LowerCorner string `xml:"lowerCorner"`
UpperCorner string `xml:"upperCorner"`
}
type GML struct {
ID string `xml:"id,attr"`
PlaceID string `xml:"Place_ID"`
StateID string `xml:"STATE_ID"`
Postcode string `xml:"POSTCODE"`
CGDN string `xml:"CGDN"`
Map100K string `xml:"MAP_100K"`
Point Point `xml:"pointProperty>Point"`
VariantName string `xml:"VARIANT_NAME"`
RecordID string `xml:"RECORD_ID"`
LatSeconds string `xml:"lat_seconds"`
Status string `xml:"STATUS"`
LongSeconds string `xml:"long_seconds"`
ConciseGAZ string `xml:"CONCISE_GAZ"`
Lattitude string `xml:"LATITUDE"`
AuthorityID string `xml:"AUTHORITY_ID"`
Longitude string `xml:"LONGITUDE"`
LongMinutes string `xml:"long_minutes"`
LatDegrees string `xml:"lat_degrees"`
NAME string `xml:"NAME"`
LatMinutes string `xml:"lat_minutes"`
ObjectID string `xml:"OBJECTID"`
FeatCode string `xml:"FEAT_CODE"`
LongDegrees string `xml:"long_degrees"`
}
type Point struct {
SrsName string `xml:"srsName,attr"`
SrsDimension string `xml:"srsDimension,attr"`
Pos string `xml:"pos"`
}
Here is the modified version of your code on the Go Playground which runs without errors.
To verify that your struct holds all the unmarshalled info from the XML:
fmt.Printf("%+v", v)
Output:
&{Xsi:http://www.w3.org/2001/XMLSchema-instance Fme:http://www.safe.com/gml/fme Gml:http://www.opengis.net/gml Xlink:http://www.w3.org/1999/xlink Envelope:{SrsName:EPSG:3112 SrsDimension:2 LowerCorner:45.2921142578125 -80.2166748046875 UpperCorner:169.000122070313 -9.14251708984375} SchemaLocation:http://www.safe.com/gml/fme tblMainGML.xsd FeaturesGML:[{ID:id5255fa48-42b3-43d1-9e0d-b2ba8b57a936 PlaceID:45880 StateID:QLD Postcode: CGDN:N Map100K:7272 Point:{SrsName:EPSG:3112 SrsDimension:2 Pos:141.625915527344 -12.5836181640625} VariantName: RecordID:QLD48234 LatSeconds:0 Status:U LongSeconds:32 ConciseGAZ:N Lattitude:-12.58361 AuthorityID:QLD Longitude:141.62583 LongMinutes:37 LatDegrees:-12 NAME:HATCHMAN POINT LatMinutes:35 ObjectID:1 FeatCode:PT LongDegrees:141}]}