Ich dekodiere einige XML, die nur String-Werte und Attribute enthält. Es enthält auch ein paar Instanzen von "&"
, was unglücklich ist, und ich möchte das nur zu "&"
eher als "&"
dekodieren. Ich werde auch etwas mehr mit diesen Zeichenfolgenwerten arbeiten, in denen ich das Zeichen "|"
nie erscheinen lassen möchte, und deshalb möchte ich jede "|"
Instanz durch "%7C"
ersetzen.Benutzerdefinierte String-Übersetzung beim Dekodieren von XML in Golang
Ich konnte diese Änderungen tun strings.Replace
nach der Decodierung verwendet wird, aber da die Decodierung bereits eine ähnliche Arbeit tun (schließlich ist es "&"
-"&"
übersetzen) Ich kann es zur gleichen Zeit tun möchten.
Die Dateien ich sind sehr groß werden, Parsen, also werde ich hier zu http://blog.davidsingleton.org/parsing-huge-xml-files-with-go/
ähnlich, etwas zu tun ist, ist ein kurzes Beispiel XML-Datei:
<?xml version="1.0" encoding="utf-8"?>
<tests>
<test_content>X&amp;Y is a dumb way to write XnY | also here's a pipe.</test_content>
<test_attr>
<test name="Normal" value="still normal" />
<test name="X&amp;Y" value="should be the same as X&Y | XnY would have been easier." />
</test_attr>
</tests>
Und einige Code Go, die Standard-Decodierung tut und druckt die Ergebnisse aus:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type XMLTests struct {
Content string `xml:"test_content"`
Tests []*XMLTest `xml:"test_attr>test"`
}
type XMLTest struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
func main() {
xmlFile, err := os.Open("test.xml")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer xmlFile.Close()
var q XMLTests
decoder := xml.NewDecoder(xmlFile)
// I tried this to no avail:
// decoder.Entity = make(map[string]string)
// decoder.Entity["|"] = "%7C"
// decoder.Entity["&amp;"] = "&"
var inElement string
for {
t, _ := decoder.Token()
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
inElement = se.Name.Local
if inElement == "tests" {
decoder.DecodeElement(&q, &se)
}
default:
}
}
fmt.Println(q.Content)
for _, t := range q.Tests {
fmt.Printf("\t%s\t\t%s\n", t.Name, t.Value)
}
}
Wie ändere ich diesen Code, um zu bekommen, was ich will? zB: Wie passt man den Decoder an?
Ich schaute auf die Dokumente, speziell https://golang.org/pkg/encoding/xml/#Decoder und versuchte, mit der Entity Map zu spielen, aber ich konnte keine Fortschritte machen.
Edit:
Basierend auf den Kommentaren, habe ich das Beispiel von Multiple-types decoder in golang gefolgt und hinzugefügt/geändert Folgendes obigen Code:
type string2 string
type XMLTests struct {
Content string2 `xml:"test_content"`
Tests []*XMLTest `xml:"test_attr>test"`
}
type XMLTest struct {
Name string2 `xml:"name,attr"`
Value string2 `xml:"value,attr"`
}
func (s *string2) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var content string
if err := d.DecodeElement(&content, &start); err != nil {
return err
}
content = strings.Replace(content, "|", "%7C", -1)
content = strings.Replace(content, "&", "&", -1)
*s = string2(content)
return nil
}
, die für die test_content
funktioniert aber nicht für die Attribute?
X&Y is a dumb way to write XnY %7C also here's a pipe.
Normal still normal
X&Y should be the same as X&Y | XnY would have been easier.
Sie wollen tatsächlich etwas tun http://stackoverflow.com/questions/21164455/multiple-types- decoder-in-golang, wo Sie eine Implementierung von 'UnmarshalXML' bereitstellen, obwohl ich persönlich nicht denke, dass es besser ist, als nur eine Funktion wie' type.Sanatize() 'nach der Tat aufzurufen. Ich persönlich würde letzteres nehmen, weil es weniger verschleiert ist. Ich sehe benutzerdefinierte 'Unmarshal'-Implementierungen sehr ähnlich wie Operatorüberladung, mehr Verwirrung und Arbeit, als sie wert sind. – evanmcdonnal
@evanmcdonnal Beide Optionen sind ziemlich unbefriedigend. Ich meine, der existierende Decoder ändert bereits "&" zu "&" zusammen mit anderen Standard-XML-Escapes, ist es wirklich so hart-codiert, dass ich nicht einfach dort mitkommen kann? Ich versuche nicht, die XML-Regeln wie in der anderen Frage zu brechen. –
Ich meine, das ist es, was die Implementierung von 'UnmarshalXML' bewirkt ... Sie können einfach alles decodieren, String ersetzen und dann das normale' Unmarshal' aufrufen, es ist nicht so, als müssten Sie die harte Arbeit machen. Ich bin nicht besonders in die XML-Spezifikation eingeweiht, aber afaik '|' hat keine spezielle Bezeichnung, also warum würdest du erwarten, dass es so behandelt werden kann wie ein Escape-Zeichen? Ja, ich würde erwarten, dass diese Liste von Sonderzeichen hart codiert und nicht exportiert wird, warum sollte es nicht sein? – evanmcdonnal