我当前的当前任务是使用golang读取进入系统的不同xml负载。 xml有效负载可能具有不同的根标记名称。根标签名称不同意味着xml具有完全不同的含义。
我已经使用编码/ xml已有一段时间了,但是我发现无法通过一个Unmarshal调用来读取那些xml负载,而无需在未提取或提取根名称之前进行操作的情况下对其进行读取。 。
这是手头任务的简化示例,分别读取2个xml:
package main
import (
"fmt"
"encoding/xml"
)
type Boxes struct {
Length []float64
}
type Bottles struct {
Diameter []float64
}
var Box_xml = []byte("<Boxes><Length>45</Length><Length>41</Length></Boxes>")
var Bottle_xml = []byte("<Bottles><Diameter>23</Diameter><Diameter>25</Diameter></Bottles>")
func main() {
box := Boxes{}
xml.Unmarshal(Box_xml, &box)
bottle := Bottles{}
xml.Unmarshal(Bottle_xml, &bottle)
fmt.Println(box, bottle)
}
此代码打印
{[45 41]} {[23 25]}
我当前用于在单个调用中处理任意传入消息的“最佳”解决方案将是向这些xml添加一个根标记,并在中央结构中读取它们-像这样:
package main
import (
"fmt"
"encoding/xml"
)
type Boxes struct {
Length []float64
}
type Bottles struct {
Diameter []float64
}
type Delivery struct {
Boxes Boxes
Bottles Bottles
}
var Box_xml = []byte("<Delivery><Boxes><Length>45</Length><Length>41</Length></Boxes></Delivery>")
var Bottle_xml = []byte("<Delivery><Bottles><Diameter>23</Diameter><Diameter>25</Diameter></Bottles></Delivery>")
func main() {
delivery := Delivery{}
xml.Unmarshal(Box_xml, &delivery)
fmt.Println(delivery )
delivery = Delivery{}
xml.Unmarshal(Bottle_xml, &delivery)
fmt.Println(delivery)
}
此代码打印
{{[45 41]} {[]}}
{{[]} {[23 25]}}
这将是构造结果以供以后处理的好方法。
我如何做到而不必在有效负载中添加人工根标签?
最佳答案
您可以创建xml解码器,并使用Token
方法逐节点解析xml输入。它不会解析所有文档。查看更多here。
token 返回输入流中的下一个XML token 。在输入流的末尾, token 返回nil,io.EOF。
返回的 token 数据中的 byte slice 引用解析器的内部缓冲区,并且仅在下一次调用Token之前保持有效。要获取字节的副本,请调用CopyToken或 token 的Copy方法。
token 将自关闭元素扩展为连续调用返回的单独的开始和结束元素。
token 保证返回的StartElement和EndElement token 正确嵌套和匹配:如果Token在所有预期的结束元素之前遇到意外的结束元素或EOF,它将返回错误。
这只是一个示例,如何确定具有的xml类型和需要解析的结构:
package main
import (
"encoding/xml"
"log"
"strings"
)
type Boxes struct {
Length []float64
}
type Bottles struct {
Diameter []float64
}
type DeliveryBoxes struct {
Boxes Boxes
}
type DeliveryBottles struct {
Bottles Bottles
}
const (
BoxXML = "<Delivery><Boxes><Length>45</Length><Length>41</Length></Boxes></Delivery>"
BottleXML = "<Delivery><Bottles><Diameter>23</Diameter><Diameter>25</Diameter></Bottles></Delivery>"
)
func main() {
var err error
var xmlReader = strings.NewReader(BoxXML)
var decoder = xml.NewDecoder(xmlReader)
// start with a first token 'Delivery'
t, err := decoder.Token()
if err != nil {
log.Fatalln(err)
}
// next token is a next node: 'Boxes' or 'Bottles'
t, err = decoder.Token()
if err != nil {
log.Fatalln(err)
}
startElement := t.(xml.StartElement)
// create new reader to start from the beginning
xmlReader = strings.NewReader(BoxXML)
switch startElement.Name.Local {
case "Boxes":
var delivery DeliveryBoxes
if err := xml.NewDecoder(xmlReader).Decode(&delivery); err != nil {
log.Fatalln(err)
}
log.Println(delivery)
case "Bottles":
var delivery DeliveryBottles
if err := xml.NewDecoder(xmlReader).Decode(&delivery); err != nil {
log.Fatalln(err)
}
log.Println(delivery)
}
}
通常,我们解析前两个节点以检查结构类型,然后使用定义的结构解析完整的xml输入。您可以将switch语句移至单个函数,并将interface{}
类型用于delivery
变量。无论如何,这是一个向您展示可以确定xml输入的数据格式而无需解析整个输入的示例。
关于xml - 如何使用golang编码/xml读取具有不同根的xml内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60324774/