在 Go 中,如何解析具有混合元素/chardata/elements/chardata

假设我有一个可以多次引用元素的结构:


    <?xml version="1.0" encoding="UTF-8"?>

    <book category="cooking">

      <title>Everyday Italian</title>

      <author>Giada De Laurentiis</author>

      <year>2005</year>

      <price>30.00</price>

      Blah Blah Blah Bleh Blah of <year/> written by <author/>

    </book>

我如何解析这个 XML(或者更好地说,我如何描述结构),以便我可以拥有对它的这些内部引用?


    type Book struct{

       t string `xml:"book>title"`

       p string `xml:"book>price"`

       y string `xml:"book>year"`

       a string `xml:"book>author"`

       blah string ???????

    }

天真的方法(https://go.dev/play/p/JVM98pCcI0D),只是描述blah为cdata显然是错误的,因为引用<year/>和<author/>正在丢失。


在这里定义的正确方法是什么blah,使得它的内部结构,解析后仍然可用?


白猪掌柜的
浏览 66回答 1
1回答

qq_笑_17

基于icza评论的解决方案:func (b *Book) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; t, err := d.Token()&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != io.EOF {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return nil&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; switch t := t.(type) {&nbsp; &nbsp; &nbsp; &nbsp; case xml.StartElement:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var f interface{} // field&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var r string&nbsp; &nbsp; &nbsp; // replace&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch t.Name.Local {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "title":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = &b.Title&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "author":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(b.Author) > 0 { // if "author" was already decoded then assume this is the element in the "blah chardata"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = b.Author // if you want <author/> to appear in Text then do `r = "<author/>"` instead&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = &b.Author&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "year":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(b.Year) > 0 { // same logic as for author above&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = b.Year&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = &b.Year&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "price":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = &b.Price&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if f != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err := d.DecodeElement(f, &t); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(r) > 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b.Text += " " + r + " " // add empty space for padding the replacement string&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; case xml.CharData:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s := strings.TrimSpace(string(t))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(s) > 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b.Text += s&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return nil}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go