xml - 使用 Go 解析时如何检查输入 XML 中的错误?
问题描述
我是 golang 的初学者,正在编写 XML 解析器。
我的目标是希望包括检查 xml 文件的格式是否正确,检查元素和属性是否缺少括号或拼写错误的单词。如果缺少括号或拼写错误的单词,代码可能会引发异常,通知用户更正错误。
让我们以一个 xml 文件的具体示例为例example.xml
:
<?xml version="1.0" encoding="utf-8"?>
<servers version="1">
<server>
<model name="Cisco" type="modelA"></model>
<serverName>Tokyo_VPN</serverName>
<serverIP>127.0.0.1</serverIP>
</server>
<server>
<model name="Dell" type="modelB"></model>
<serverName>Moscow_VPN</serverName>
<serverIP>127.0.0.2</serverIP>
</server>
</servers>
使用标准的 Go 包"encoding/xml"
,定义结构和解析 XML 很简单,如下所示:
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
)
type Servers struct {
XMLName xml.Name `xml:"servers"`
Version string `xml:"version,attr"`
Svs []server `xml:"server"`
}
type server struct {
XMLName xml.Name `xml:"server"`
Model model `xml:"model"`
ServerName string `xml:"serverName"`
ServerIP string `xml:"serverIP"`
}
type model struct {
XMLName xml.Name `xml:"model"`
Name string `xml:"name,attr"`
Type string `xml:"type,attr"`
}
func main() {
// open the xml file
file, err := os.Open("toy.xml")
if err != nil {
fmt.Printf("error: %v", err)
return
}
defer file.Close()
// read the opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(file)
var allservers Servers
err = xml.Unmarshal(byteValue, &allservers)
if err != nil {
fmt.Printf("error: %v", err)
return
}
fmt.Println(allservers)
}
缺少括号等错误即
<model name="Cisco" type="modelA"></model
或拼写错误的属性/元素,例如
<serverNammme>Moscow_VPN</serverName>
,这些错误是通过 XML 语法错误捕获的。
但是,可能会发生其他错误。例如,属性拼写错误的单词:
<model namMMe="Cisco" typeE="modelA"></model>
尽管这是有效的 XML 格式,但我想将此视为错误,因为(出于我的目的)这些是输入 XML 文件中的拼写错误,应该更正。
这将在没有任何错误的情况下被解析为以下内容:
{{ servers} 1 [{{ server} {{ model} } Tokyo_VPN 127.0.0.1} {{ server} {{ model} Dell modelB} Moscow_VPN 127.0.0.2}]}
我怎样才能捕捉到这些错误并抛出错误?
解决方案
如果你去 encoding/xml 的文档
https://golang.org/pkg/encoding/xml/#Unmarshal
有一个编写自定义 Marshal/Unmarshal 的例子,你只需要实现 Unmarshaler 接口
因此,您的自定义 Unmarshaler 可以在解组时检查值并返回错误
推荐阅读
- docusignapi - DocuSign 损坏的 Webhook 在线文档
- android - React Native - 单击 Flatlist 的项目(搜索列表后)
- mysql - MySQL 一张表 vs 多张表(相同数据)
- angular - Angular - 带有 routerlink url 的锚标记为 href 属性多次编码
- android - AlarmManager setRepeating Interval 问题
- react-native - Expo:即使浏览器会话过期,WebBrowser.openAuthSessionAsync 和相关调用也会跳过用户输入
- css - 基础切换画布菜单
- javascript - 重新格式化数组对象 JavaScript
- javascript - 对象解构或可选链接哪个更好?
- google-cloud-platform - 节点升级弹出显示在工作节点中