假設我有一個可以多次參考元素的結構:
<?xml version="1.0" encoding="UTF-8"?>
<book category="cooking">
<title lang="en">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,使得它的內部結構,決議后仍然可用?
uj5u.com熱心網友回復:
基于icza評論的解決方案:
func (b *Book) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err != nil {
if err != io.EOF {
return err
}
return nil
}
switch t := t.(type) {
case xml.StartElement:
var f interface{} // field
var r string // replace
switch t.Name.Local {
case "title":
f = &b.Title
case "author":
if len(b.Author) > 0 { // if "author" was already decoded then assume this is the element in the "blah chardata"
r = b.Author // if you want <author/> to appear in Text then do `r = "<author/>"` instead
} else {
f = &b.Author
}
case "year":
if len(b.Year) > 0 { // same logic as for author above
r = b.Year
} else {
f = &b.Year
}
case "price":
f = &b.Price
}
if f != nil {
if err := d.DecodeElement(f, &t); err != nil {
return err
}
}
if len(r) > 0 {
b.Text = " " r " " // add empty space for padding the replacement string
}
case xml.CharData:
s := strings.TrimSpace(string(t))
if len(s) > 0 {
b.Text = s
}
}
}
return nil
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/430496.html
