changeset 372:15369b41be74

Teach WFS proxy about default namespaces.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 09 Aug 2018 17:59:28 +0200
parents d5b707bbd1d5
children 7e7e978d1cac
files controllers/externalwfs.go
diffstat 1 files changed, 79 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/controllers/externalwfs.go	Thu Aug 09 17:21:12 2018 +0200
+++ b/controllers/externalwfs.go	Thu Aug 09 17:59:28 2018 +0200
@@ -226,7 +226,7 @@
 		return strings.Replace(s, from, to, -1)
 	}
 
-	var ns nsdef
+	var n nsdef
 
 tokens:
 	for {
@@ -240,46 +240,48 @@
 
 		switch t := tok.(type) {
 		case xml.StartElement:
-			ns = ns.push()
 			t = t.Copy()
 
-			attr := make([]xml.Attr, len(t.Attr))
+			isDef := n.isDef(t.Name.Space)
+			n = n.push()
 
-			for i, at := range t.Attr {
-				at.Value = replace(at.Value)
-				switch {
-				case at.Name.Space == "xmlns":
-					ns.define(at.Value, at.Name.Local)
-					at.Name.Local = "xmlns:" + at.Name.Local
-					at.Name.Space = ""
+			for i := range t.Attr {
+				t.Attr[i].Value = replace(t.Attr[i].Value)
+				n.checkDef(&t.Attr[i])
+			}
 
-				case at.Name.Space != "":
-					if s := ns.lookup(at.Name.Space); s != "" {
-						at.Name.Local = s + ":" + at.Name.Local
-						at.Name.Space = ""
-					}
-				}
+			for i := range t.Attr {
+				n.adjust(&t.Attr[i])
+			}
 
-				attr[i] = at
-			}
-			if s := ns.lookup(t.Name.Space); s != "" {
+			switch {
+			case isDef:
 				t.Name.Space = ""
-				t.Name.Local = s + ":" + t.Name.Local
+			default:
+				if s := n.lookup(t.Name.Space); s != "" {
+					t.Name.Space = ""
+					t.Name.Local = s + ":" + t.Name.Local
+				}
 			}
-			t.Attr = attr
 			tok = t
 
 		case xml.CharData:
 			tok = xml.CharData(replace(string(t)))
 
 		case xml.EndElement:
-			if s := ns.lookup(t.Name.Space); s != "" {
+			s := n.lookup(t.Name.Space)
+
+			n = n.pop()
+
+			if n.isDef(t.Name.Space) {
+				t.Name.Space = ""
+			} else if s != "" {
 				t.Name.Space = ""
 				t.Name.Local = s + ":" + t.Name.Local
-				tok = t
 			}
-			ns = ns.pop()
+			tok = t
 		}
+
 		if err := encoder.EncodeToken(tok); err != nil {
 			return err
 		}
@@ -288,31 +290,74 @@
 	return encoder.Flush()
 }
 
-type nsdef []map[string]string
+type nsframe struct {
+	def string
+	ns  map[string]string
+}
+
+type nsdef []nsframe
+
+func (n nsdef) setDef(def string) {
+	if l := len(n); l > 0 {
+		n[l-1].def = def
+	}
+}
+
+func (n nsdef) isDef(s string) bool {
+	for i := len(n) - 1; i >= 0; i-- {
+		if x := n[i].def; x != "" {
+			return s == x
+		}
+	}
+	return false
+}
+
+func (n nsdef) define(ns, s string) {
+	if l := len(n); l > 0 {
+		n[l-1].ns[ns] = s
+	}
+}
 
 func (n nsdef) lookup(ns string) string {
 	for i := len(n) - 1; i >= 0; i-- {
-		if s := n[i][ns]; s != "" {
+		if s := n[i].ns[ns]; s != "" {
 			return s
 		}
 	}
 	return ""
 }
 
+func (n nsdef) checkDef(at *xml.Attr) {
+	if at.Name.Space == "" && at.Name.Local == "xmlns" {
+		n.setDef(at.Value)
+	}
+}
+
+func (n nsdef) adjust(at *xml.Attr) {
+	switch {
+	case at.Name.Space == "xmlns":
+		n.define(at.Value, at.Name.Local)
+		at.Name.Local = "xmlns:" + at.Name.Local
+		at.Name.Space = ""
+
+	case at.Name.Space != "":
+		if n.isDef(at.Name.Space) {
+			at.Name.Space = ""
+		} else if s := n.lookup(at.Name.Space); s != "" {
+			at.Name.Local = s + ":" + at.Name.Local
+			at.Name.Space = ""
+		}
+	}
+}
+
 func (n nsdef) push() nsdef {
-	return append(n, make(map[string]string))
+	return append(n, nsframe{ns: make(map[string]string)})
 }
 
 func (n nsdef) pop() nsdef {
 	if l := len(n); l > 0 {
-		n[l-1] = nil
+		n[l-1] = nsframe{}
 		n = n[:l-1]
 	}
 	return n
 }
-
-func (n nsdef) define(ns, s string) {
-	if n != nil {
-		n[len(n)-1][ns] = s
-	}
-}