diff --git a/pkg/wfs200/capabilities.go b/pkg/wfs200/capabilities.go
index d09e083..ea36d12 100644
--- a/pkg/wfs200/capabilities.go
+++ b/pkg/wfs200/capabilities.go
@@ -123,12 +123,12 @@ type FeatureTypeList struct {
// FeatureType struct for the WFS 2.0.0
type FeatureType struct {
- Name string `xml:"Name" yaml:"name"`
- Title string `xml:"Title" yaml:"title"`
- Abstract string `xml:"Abstract" yaml:"abstract"`
- Keywords *wsc110.Keywords `xml:"ows:Keywords" yaml:"keywords"`
- DefaultCRS *wsc110.CRS `xml:"DefaultCRS" yaml:"defaultcrs"`
- OtherCRS *[]wsc110.CRS `xml:"OtherCRS" yaml:"othercrs"`
+ Name string `xml:"Name" yaml:"name"`
+ Title string `xml:"Title" yaml:"title"`
+ Abstract string `xml:"Abstract" yaml:"abstract"`
+ Keywords *[]wsc110.Keywords `xml:"ows:Keywords" yaml:"keywords"`
+ DefaultCRS *CRS `xml:"DefaultCRS" yaml:"defaultcrs"`
+ OtherCRS *[]CRS `xml:"OtherCRS" yaml:"othercrs"`
OutputFormats struct {
Format []string `xml:"Format" yaml:"format"`
} `xml:"OutputFormats" yaml:"outputformats"`
diff --git a/pkg/wfs200/crs.go b/pkg/wfs200/crs.go
new file mode 100644
index 0000000..52a2693
--- /dev/null
+++ b/pkg/wfs200/crs.go
@@ -0,0 +1,44 @@
+package wfs200
+
+import (
+ "regexp"
+ "strconv"
+)
+
+//
+const (
+ codeSpace = `urn:ogc:def:crs:EPSG:`
+)
+
+// CRS struct with namespace/authority/registry and code
+type CRS struct {
+ Namespace string //TODO maybe AuthorityType is a better name...?
+ Code int
+}
+
+// String of the EPSGCode
+func (c *CRS) String() string {
+ return c.Namespace + `:` + strconv.Itoa(c.Code)
+}
+
+// Identifier returns the EPSG
+func (c *CRS) Identifier() string {
+ return codeSpace + strconv.Itoa(c.Code)
+}
+
+// ParseString build CRS struct from input string
+func (c *CRS) ParseString(s string) {
+ c.parseString(s)
+}
+
+func (c *CRS) parseString(s string) {
+ regex := regexp.MustCompile(`(^.*):([0-9]+)`)
+ code := regex.FindStringSubmatch(s)
+ if len(code) == 3 { // code[0] is the full match, the other the parts
+ c.Namespace = codeSpace
+
+ // the regex already checks if it [0-9]
+ i, _ := strconv.Atoi(code[2])
+ c.Code = i
+ }
+}
diff --git a/pkg/wfs200/crs_test.go b/pkg/wfs200/crs_test.go
new file mode 100644
index 0000000..9175737
--- /dev/null
+++ b/pkg/wfs200/crs_test.go
@@ -0,0 +1,60 @@
+package wfs200
+
+import (
+ "testing"
+
+ "gopkg.in/yaml.v3"
+)
+
+func TestCRSParseString(t *testing.T) {
+ var tests = []struct {
+ input string
+ expectedCRS CRS
+ }{
+ 0: {}, // Empty input == empty struct
+ 1: {input: `urn:ogc:def:crs:EPSG::4326`, expectedCRS: CRS{Code: 4326, Namespace: `urn:ogc:def:crs:EPSG:`}},
+ 2: {input: `EPSG:4326`, expectedCRS: CRS{Code: 4326, Namespace: `urn:ogc:def:crs:EPSG:`}},
+ }
+
+ for k, test := range tests {
+ var crs CRS
+ crs.parseString(test.input)
+
+ if crs.Code != test.expectedCRS.Code || crs.Namespace != test.expectedCRS.Namespace {
+ t.Errorf("test: %d, expected: %v,\n got: %v", k, test.expectedCRS, crs)
+ }
+ }
+}
+
+func TestUnmarshalYAMLCrs(t *testing.T) {
+
+ var stringYAML = `defaultcrs: urn:ogc:def:crs:EPSG::4326
+othercrs:
+- EPSG:4258
+- urn:ogc:def:crs:EPSG::3857`
+
+ type FeatureType struct {
+ DefaultCRS CRS `yaml:"defaultcrs"`
+ OtherCRS []CRS `yaml:"othercrs"`
+ }
+
+ var tests = []struct {
+ yaml []byte
+ expectedcrs CRS
+ }{
+ 0: {yaml: []byte(stringYAML), expectedcrs: CRS{Code: 4326, Namespace: codeSpace}},
+ 1: {yaml: []byte(`defaultcrs: urn:ogc:def:crs:EPSG::4326`), expectedcrs: CRS{Code: 4326, Namespace: codeSpace}},
+ 2: {yaml: []byte(`defaultcrs: EPSG:4326`), expectedcrs: CRS{Code: 4326, Namespace: codeSpace}},
+ }
+ for k, test := range tests {
+ var ftl FeatureType
+ err := yaml.Unmarshal(test.yaml, &ftl)
+ if err != nil {
+ t.Errorf("test: %d, yaml.UnMarshal failed with '%s'\n", k, err)
+ } else {
+ if ftl.DefaultCRS.Code != test.expectedcrs.Code || ftl.DefaultCRS.Namespace != test.expectedcrs.Namespace {
+ t.Errorf("test: %d, expected: %v+,\n got: %v+", k, test.expectedcrs, ftl.DefaultCRS)
+ }
+ }
+ }
+}
diff --git a/pkg/wfs200/crs_xml.go b/pkg/wfs200/crs_xml.go
new file mode 100644
index 0000000..9238966
--- /dev/null
+++ b/pkg/wfs200/crs_xml.go
@@ -0,0 +1,36 @@
+package wfs200
+
+import (
+ "encoding/xml"
+ "fmt"
+)
+
+// MarshalXML Position
+func (c *CRS) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ var s = ``
+ if c.Namespace != `` {
+ s = fmt.Sprintf("%s:%d", c.Namespace, c.Code)
+ }
+
+ return e.EncodeElement(s, start)
+}
+
+// UnmarshalXML Position
+func (c *CRS) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ var crs CRS
+ for {
+ token, err := d.Token()
+ if err != nil {
+ return err
+ }
+ switch el := token.(type) {
+ case xml.CharData:
+ crs.parseString(string([]byte(el)))
+ case xml.EndElement:
+ if el == start.End() {
+ *c = crs
+ return nil
+ }
+ }
+ }
+}
diff --git a/pkg/wfs200/crs_yaml.go b/pkg/wfs200/crs_yaml.go
new file mode 100644
index 0000000..f040a09
--- /dev/null
+++ b/pkg/wfs200/crs_yaml.go
@@ -0,0 +1,16 @@
+package wfs200
+
+// UnmarshalYAML CRS
+func (c *CRS) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+
+ var crs CRS
+ crs.parseString(s)
+
+ *c = crs
+
+ return nil
+}
diff --git a/pkg/wmts100/capabilities_test.go b/pkg/wmts100/capabilities_test.go
index 47936c7..9c4cc76 100644
--- a/pkg/wmts100/capabilities_test.go
+++ b/pkg/wmts100/capabilities_test.go
@@ -51,8 +51,8 @@ var contentsWithLegend = Contents{
func TestBuildStyleWithLegend(t *testing.T) {
expected := ``
output, _ := xml.MarshalIndent(contentsWithLegend.Layer[0].Style, "", " ")
@@ -91,8 +91,8 @@ var contentsWithoutLegend = Contents{
func TestBuildStyleWithoutLegend(t *testing.T) {
expected := ``
output, _ := xml.MarshalIndent(contentsWithoutLegend.Layer[0].Style, "", " ")
if string(output) != expected {
diff --git a/pkg/wsc110/keywords.go b/pkg/wsc110/keywords.go
index 3077915..7eeb266 100644
--- a/pkg/wsc110/keywords.go
+++ b/pkg/wsc110/keywords.go
@@ -2,6 +2,9 @@ package wsc110
// Keywords in struct for repeatability
type Keywords struct {
- Keyword []string `xml:"ows:Keyword" yaml:"keyword"`
- Type string `xml:"ows:Type,omitempty" yaml:"type"`
+ Keyword []string `xml:"ows:Keyword"`
+ Type *struct {
+ Text string `xml:",chardata"`
+ CodeSpace *string `xml:"codeSpace,attr,omitempty"`
+ } `xml:"ows:Type"`
}