golang从XML自动生成Go结构体定义插件库zek的使用
使用zek库从XML自动生成Go结构体定义
zek是一个用于从XML文档创建Go结构体的原型工具。它由莱比锡大学图书馆开发,旨在缩短从原始XML到可访问XML数据的Go结构体的时间。
基本用法
给定一个XML文件,可以通过以下命令生成Go结构体:
$ curl -s https://raw.githubusercontent.com/miku/zek/master/fixtures/e.xml | zek -e
// Rss was generated 2018-08-30 20:24:14 by tir on sol.
type Rss struct {
XMLName xml.Name `xml:"rss"`
Text string `xml:",chardata"`
Rdf string `xml:"rdf,attr"`
Dc string `xml:"dc,attr"`
Geoscan string `xml:"geoscan,attr"`
Media string `xml:"media,attr"`
Gml string `xml:"gml,attr"`
Taxo string `xml:"taxo,attr"`
Georss string `xml:"georss,attr"`
Content string `xml:"content,attr"`
Geo string `xml:"geo,attr"`
Version string `xml:"version,attr"`
Channel struct {
Text string `xml:",chardata"`
Title string `xml:"title"` // ESS New Releases (Display...
Link string `xml:"link"` // http://tinyurl.com/ESSNew...
Description string `xml:"description"` // New releases from the Ear...
LastBuildDate string `xml:"lastBuildDate"` // Mon, 27 Nov 2017 00:06:35...
Item []struct {
Text string `xml:",chardata"`
Title string `xml:"title"` // Surficial geology, Aberde...
Link string `xml:"link"` // https://geoscan.nrcan.gc....
Description string `xml:"description"` // Geological Survey of Cana...
Guid struct {
Text string `xml:",chardata"` // 304279, 306212, 306175, 3...
IsPermaLink string `xml:"isPermaLink,attr"`
} `xml:"guid"`
PubDate string `xml:"pubDate"` // Fri, 24 Nov 2017 00:00:00...
Polygon []string `xml:"polygon"` // 64.0000 -98.0000 64.0000 ...
Download string `xml:"download"` // https://geoscan.nrcan.gc....
License string `xml:"license"` // http://data.gc.ca/eng/ope...
Author string `xml:"author"` // Geological Survey of Cana...
Source string `xml:"source"` // Geological Survey of Cana...
SndSeries string `xml:"SndSeries"` // Bedford Institute of Ocea...
Publisher string `xml:"publisher"` // Natural Resources Canada,...
Edition string `xml:"edition"` // prelim., surficial data m...
Meeting string `xml:"meeting"` // Geological Association of...
Documenttype string `xml:"documenttype"` // serial, open file, serial...
Language string `xml:"language"` // English, English, English...
Maps string `xml:"maps"` // 1 map, 5 maps, Publicatio...
Mapinfo string `xml:"mapinfo"` // surficial geology, surfic...
Medium string `xml:"medium"` // on-line; digital, digital...
Province string `xml:"province"` // Nunavut, Northwest Territ...
Nts string `xml:"nts"` // 066B, 095J; 095N; 095O; 0...
Area string `xml:"area"` // Aberdeen Lake, Mackenzie ...
Subjects string `xml:"subjects"`
Program string `xml:"program"` // GEM2: Geo-mapping for Ene...
Project string `xml:"project"` // Rae Province Project Mana...
Projectnumber string `xml:"projectnumber"` // 340521, 343202, 340557, 3...
Abstract string `xml:"abstract"` // This new surficial geolog...
Links string `xml:"links"` // Online - En ligne (PDF, 9...
Readme string `xml:"readme"` // readme | https://geoscan....
PPIid string `xml:"PPIid"` // 34532, 35096, 35438, 2563...
} `xml:"item"`
} `xml:"channel"`
}
安装
使用以下命令安装zek:
$ go install github.com/miku/zek/cmd/zek@latest
命令选项
$ zek -h
-B use a fixed banner string (e.g. for CI)
-C emit less compact struct
-F skip formatting
-I use verbatim innerxml instead of chardata
-P string
if set, write out struct within a package with the given name
-S int
read at most this many tags, approximately (0=unlimited)
-c emit more compact struct (noop, as this is the default since 0.1.7)
-d debug output
-e add comments with example
-j add JSON tags
-m omit empty Text fields
-max-examples int
limit number of examples (default 10)
-n string
use a different name for the top-level struct
-o string
if set, write to output file, not stdout
-p write out an example program
-s strict parsing and writing
-t string
emit struct for tag matching this name
-u filter out duplicated examples
-version
show version
-x int
max chars for example (default 25)
示例程序
zek可以生成一个示例程序来解析XML:
$ zek -C -p < fixtures/a.xml > sample.go && go run sample.go < fixtures/a.xml | jq . && rm sample.go
{
"XMLName": {
"Space": "",
"Local": "a"
},
"Text": ""
}
更复杂的示例:
$ zek < fixtures/d.xml
// Root was generated 2019-06-11 16:27:04 by tir on hayiti.
type Root struct {
XMLName xml.Name `xml:"root"`
Text string `xml:",chardata"`
A []struct {
Text string `xml:",chardata"`
B []struct {
Text string `xml:",chardata"`
C string `xml:"c"`
D string `xml:"d"`
} `xml:"b"`
} `xml:"a"`
}
$ zek -p < fixtures/d.xml > sample.go && go run sample.go < fixtures/d.xml | jq . && rm sample.go
{
"XMLName": {
"Space": "",
"Local": "root"
},
"Text": "\n\n\n\n",
"A": [
{
"Text": "\n \n \n",
"B": [
{
"Text": "\n \n ",
"C": "Hi",
"D": ""
},
{
"Text": "\n \n \n ",
"C": "World",
"D": ""
}
]
},
{
"Text": "\n \n",
"B": [
{
"Text": "\n \n ",
"C": "Hello",
"D": ""
}
]
},
{
"Text": "\n \n",
"B": [
{
"Text": "\n \n ",
"C": "",
"D": "World"
}
]
}
]
}
生成包
如果你想在构建过程中包含生成的文件,可以使用-P
和-o
选项:
$ zek -P mypkg -o data.go < fixtures/b.xml
这将在data.go
文件中写入以下内容:
// Code generated by zek; DO NOT EDIT.
package mypkg
import "encoding/xml"
// A was generated 2021-09-16 11:23:06 by tir on trieste.
type A struct {
XMLName xml.Name `xml:"a"`
Text string `xml:",chardata"`
B string `xml:"b"`
}
优缺点
优点:
- 适用于非递归结构
- 不需要XSD或DTD
- 相对方便访问属性、子元素和文本
- 生成单一结构体,表示形式紧凑
- 简单的用户界面
- 带有示例的注释
- 跨多个文件的模式推断
缺点:
- 实验性、早期、不稳定原型
- 不支持递归类型
- 没有类型推断,所有内容都作为字符串访问
zek是一个有用的工具,可以帮助开发者快速从XML文档生成Go结构体,从而简化XML数据的处理过程。
更多关于golang从XML自动生成Go结构体定义插件库zek的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang从XML自动生成Go结构体定义插件库zek的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用 zek 从 XML 自动生成 Go 结构体定义
zek 是一个强大的 Go 库,用于从 XML 文档自动生成 Go 结构体定义。它能够分析 XML 结构并创建对应的 Go 类型,大大简化了处理 XML 数据的工作。
安装 zek
go get github.com/miku/zek
基本使用方法
1. 从 XML 生成 Go 结构体
package main
import (
"fmt"
"log"
"os"
"github.com/miku/zek"
)
func main() {
// 示例 XML 数据
xmlData := `
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J.K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
`
// 解析 XML 并生成结构体
root, err := zek.ParseString(xmlData)
if err != nil {
log.Fatal(err)
}
// 生成 Go 代码
code, err := zek.Render(root)
if err != nil {
log.Fatal(err)
}
fmt.Println(code)
}
2. 自定义生成选项
// 使用配置选项
config := zek.Config{
PackageName: "models", // 指定包名
RootElement: "bookstore", // 指定根元素
SkipComments: true, // 跳过注释
}
code, err := zek.RenderWithConfig(root, config)
if err != nil {
log.Fatal(err)
}
fmt.Println(code)
3. 从文件读取 XML
func generateFromFile(filename string) {
// 读取 XML 文件
xmlFile, err := os.ReadFile(filename)
if err != nil {
log.Fatal(err)
}
root, err := zek.Parse(xmlFile)
if err != nil {
log.Fatal(err)
}
code, err := zek.Render(root)
if err != nil {
log.Fatal(err)
}
// 将生成的代码写入文件
err = os.WriteFile("generated.go", []byte(code), 0644)
if err != nil {
log.Fatal(err)
}
}
高级特性
1. 处理 XML 属性
zek 会自动将 XML 属性转换为结构体字段。例如,对于 <title lang="en">
,会生成:
type Title struct {
Lang string `xml:"lang,attr"`
Text string `xml:",chardata"`
}
2. 处理重复元素
对于重复出现的同名元素,zek 会生成切片类型的字段:
type Bookstore struct {
Book []Book `xml:"book"`
}
3. 类型推断
zek 会尝试推断字段类型:
- 数字值转换为 float64
- “true”/“false” 转换为 bool
- 其他作为字符串处理
实际应用示例
假设我们有一个复杂的 XML 配置文件:
<config>
<server>
<host>127.0.0.1</host>
<port>8080</port>
<ssl enabled="true">
<cert>server.crt</cert>
<key>server.key</key>
</ssl>
</server>
<database>
<name>appdb</name>
<user>admin</user>
<password>secret</password>
<connections max="100" idle="10"/>
</database>
</config>
使用 zek 生成的 Go 结构体:
package models
type Config struct {
Server Server `xml:"server"`
Database Database `xml:"database"`
}
type Server struct {
Host string `xml:"host"`
Port int `xml:"port"`
Ssl Ssl `xml:"ssl"`
}
type Ssl struct {
Enabled bool `xml:"enabled,attr"`
Cert string `xml:"cert"`
Key string `xml:"key"`
}
type Database struct {
Name string `xml:"name"`
User string `xml:"user"`
Password string `xml:"password"`
Connections Connections `xml:"connections"`
}
type Connections struct {
Max int `xml:"max,attr"`
Idle int `xml:"idle,attr"`
}
注意事项
- 对于大型 XML 文件,zek 可能需要调整内存设置
- 生成的代码可能需要手动调整以符合项目规范
- 复杂的 XML 命名空间支持可能需要额外处理
- 生成的代码通常需要配合
encoding/xml
包使用
zek 是一个强大的工具,可以显著减少处理 XML 数据时的样板代码编写工作,特别适合需要与 XML 接口交互的项目。