亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Golang 中解碼 XML 時自定義字符串翻譯

在 Golang 中解碼 XML 時自定義字符串翻譯

Go
至尊寶的傳說 2022-01-17 10:17:34
我正在解碼一些僅包含字符串值和屬性的 XML。它還"&amp;amp;"包含"&"一些"&amp;". 我還將對這些字符串值做更多的工作,我需要字符"|"永遠不會出現,所以我想"|"用"%7C".我可以strings.Replace在解碼后使用這些更改,但由于解碼已經在做類似的工作(畢竟它確實轉換"&amp;"為"&")我想同時做。我要解析的文件很大,所以我會做一些類似于http://blog.davidsingleton.org/parsing-huge-xml-files-with-go/這是一個簡短的示例 xml 文件:<?xml version="1.0" encoding="utf-8"?><tests>    <test_content>X&amp;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;amp;Y" value="should be the same as X&amp;Y | XnY would have been easier." />    </test_attr></tests>還有一些執行標準解碼并打印出結果的 Go 代碼:package mainimport (    "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;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)    }}如何修改此代碼以獲得我想要的?即:如何定制解碼器?我查看了文檔,特別是https://golang.org/pkg/encoding/xml/#Decoder并嘗試使用實體地圖,但我無法取得任何進展。
查看完整描述

1 回答

?
忽然笑

TA貢獻1806條經驗 獲得超5個贊

要處理屬性,可以使用UnmarshalerAttr接口與UnmarshalXMLAttr方法。你的例子就變成了:


package main


import (

    "encoding/xml"

    "fmt"

    "strings"

)


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 decode(s string) string2 {

    s = strings.Replace(s, "|", "%7C", -1)

    s = strings.Replace(s, "&amp;", "&", -1)

    return string2(s)

}


func (s *string2) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {

    var content string

    if err := d.DecodeElement(&content, &start); err != nil {

        return err

    }

    *s = decode(content)

    return nil

}


func (s *string2) UnmarshalXMLAttr(attr xml.Attr) error {

    *s = decode(attr.Value)

    return nil

}


func main() {

    xmlData := `<?xml version="1.0" encoding="utf-8"?>

<tests>

    <test_content>X&amp;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;amp;Y" value="should be the same as X&amp;Y | XnY would have been easier." />

    </test_attr>

</tests>`

    xmlFile := strings.NewReader(xmlData)


    var q XMLTests


    decoder := xml.NewDecoder(xmlFile)

    decoder.Decode(&q)


    fmt.Println(q.Content)

    for _, t := range q.Tests {

        fmt.Printf("\t%s\t\t%s\n", t.Name, t.Value)

    }

}

輸出:


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 %7C XnY would have been easier.

(您可以在Go 操場上進行測試。)


因此,如果string2在任何地方使用都適合您,那么這應該可以解決問題。


(編輯:更簡單的代碼,不使用DecodeElement和類型開關......)


查看完整回答
反對 回復 2022-01-17
  • 1 回答
  • 0 關注
  • 209 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號