golang XML与JSON互转及路径查询插件库mxj的使用

Golang XML与JSON互转及路径查询插件库mxj的使用

mxj是一个Go语言库,用于在map[string]interface{}、XML和JSON之间进行编码/解码,并通过键或键路径(包括通配符)从map中提取/修改值。

安装

使用go.mod安装:

go get github.com/clbanning/mxj/v2@v2.7

导入包:

import "github.com/clbanning/mxj/v2"

基本功能

XML与map[string]interface{}互转

type Map map[string]interface{}

// 从XML创建Map值
mv, err := NewMapXml(xmlValue) // 解码
xmlValue, err := mv.Xml()      // 编码

// 从io.Reader读取XML创建Map
mv, err := NewMapXmlReader(xmlReader)         // 重复调用可处理流
mv, raw, err := NewMapXmlReaderRaw(xmlReader) // 'raw'是解码的原始XML

// 将Map写入XML Writer
err := mv.XmlWriter(xmlWriter)
raw, err := mv.XmlWriterRaw(xmlWriter) // 'raw'是写入的原始XML

// 格式化输出
xmlValue, err := mv.XmlIndent(prefix, indent, ...)
err := mv.XmlIndentWriter(xmlWriter, prefix, indent, ...)
raw, err := mv.XmlIndentWriterRaw(xmlWriter, prefix, indent, ...)

批量处理XML

err := HandleXmlReader(xmlReader, mapHandler(Map), errHandler(error))
err := HandleXmlReaderRaw(xmlReader, mapHandler(Map, []byte), errHandler(error, []byte))

结构体与Map互转

mv, err := NewMapStruct(structVal)  // 结构体转Map
err := mv.Struct(structPointer)     // Map转结构体

提取和修改Map值

// 获取键的所有路径
paths := mv.PathsForKey(key)

// 获取键的最短路径
path := mv.PathForKeyShortest(key)

// 获取键的值
values, err := mv.ValuesForKey(key, subkeys)
values, err := mv.ValuesForPath(path, subkeys)

// 更新键的值
count, err := mv.UpdateValuesForPath(newVal, path, subkeys)

// 获取所有叶子节点
leafnodes := mv.LeafNodes()
leafvalues := mv.LeafValues()

// 创建新Map
newMap, err := mv.NewMap("oldKey_1:newKey_1", "oldKey_2:newKey_2", ..., "oldKey_N:newKey_N")
newMap, err := mv.NewMap("oldKey1", "oldKey3", "oldKey5") // 'mv'的子集

完整示例

XML转JSON示例

package main

import (
	"encoding/json"
	"fmt"
	"github.com/clbanning/mxj/v2"
)

func main() {
	xmlData := []byte(`
		<person>
			<name>John Doe</name>
			<age>30</age>
			<address>
				<street>123 Main St</street>
				<city>Anytown</city>
			</address>
		</person>
	`)

	// 将XML转换为Map
	m, err := mxj.NewMapXml(xmlData)
	if err != nil {
		fmt.Println("Error converting XML to map:", err)
		return
	}

	// 将Map转换为JSON
	jsonData, err := json.MarshalIndent(m, "", "  ")
	if err != nil {
		fmt.Println("Error converting map to JSON:", err)
		return
	}

	fmt.Println("JSON output:")
	fmt.Println(string(jsonData))

	// 查询特定路径的值
	values, err := m.ValuesForPath("person.address.street")
	if err != nil {
		fmt.Println("Error getting value for path:", err)
		return
	}

	fmt.Println("\nStreet value:", values[0])
}

JSON转XML示例

package main

import (
	"fmt"
	"github.com/clbanning/mxj/v2"
)

func main() {
	jsonData := []byte(`
		{
			"person": {
				"name": "John Doe",
				"age": 30,
				"address": {
					"street": "123 Main St",
					"city": "Anytown"
				}
			}
		}
	`)

	// 将JSON转换为Map
	m, err := mxj.NewMapJson(jsonData)
	if err != nil {
		fmt.Println("Error converting JSON to map:", err)
		return
	}

	// 将Map转换为XML
	xmlData, err := m.XmlIndent("", "  ")
	if err != nil {
		fmt.Println("Error converting map to XML:", err)
		return
	}

	fmt.Println("XML output:")
	fmt.Println(string(xmlData))
}

XML解析约定

使用NewMapXml():

  • 属性通过在属性标签前加连字符"-"解析到map[string]interface{}值
  • 如果元素是简单元素且有属性,元素值在map[string]interface{}表示中使用键"#text"
  • XML注释、指令和处理指令被忽略
  • 如果调用了CoerceKeysToLower(),结果键将变为小写

使用NewMapXmlSeq():

  • 属性解析到map["#attr"]map[<attr_label>]map[string]interface{}值
  • 除根元素外,所有元素都有"#seq"键
  • 注释、指令和处理指令使用"#comment"、"#directive"和"#procinst"键解组到Map中
  • 保留命名空间语法

XML编码约定

  • ‘nil’ Map值编码为<tag/>
  • 不能保证编码的XML文档与解码的相同。如果需要保持元素序列,请使用NewMapXmlSeq()和mv.XmlSeq()

更多关于golang XML与JSON互转及路径查询插件库mxj的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang XML与JSON互转及路径查询插件库mxj的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang中XML与JSON互转及mxj库使用指南

在Go语言中处理XML和JSON数据转换以及路径查询是一个常见需求,mxj库提供了强大的功能来实现这些操作。下面我将详细介绍如何使用mxj库进行XML与JSON的转换以及路径查询。

安装mxj库

首先需要安装mxj库:

go get github.com/clbanning/mxj

XML转JSON

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
)

func main() {
	xmlData := `
		<person>
			<name>John Doe</name>
			<age>30</age>
			<address>
				<street>123 Main St</street>
				<city>New York</city>
			</address>
		</person>
	`

	// 将XML转换为map
	m, err := mxj.NewMapXml([]byte(xmlData))
	if err != nil {
		fmt.Println("XML解析错误:", err)
		return
	}

	// 将map转换为JSON
	jsonData, err := m.Json()
	if err != nil {
		fmt.Println("JSON转换错误:", err)
		return
	}

	fmt.Println("转换后的JSON:")
	fmt.Println(string(jsonData))
}

JSON转XML

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
)

func main() {
	jsonData := `{
		"person": {
			"name": "John Doe",
			"age": 30,
			"address": {
				"street": "123 Main St",
				"city": "New York"
			}
		}
	}`

	// 将JSON转换为map
	m, err := mxj.NewMapJson([]byte(jsonData))
	if err != nil {
		fmt.Println("JSON解析错误:", err)
		return
	}

	// 将map转换为XML
	xmlData, err := m.Xml()
	if err != nil {
		fmt.Println("XML转换错误:", err)
		return
	}

	fmt.Println("转换后的XML:")
	fmt.Println(string(xmlData))
}

路径查询

mxj提供了强大的路径查询功能,类似于XPath:

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
)

func main() {
	xmlData := `
		<persons>
			<person id="1">
				<name>John Doe</name>
				<age>30</age>
			</person>
			<person id="2">
				<name>Jane Smith</name>
				<age>25</age>
			</person>
		</persons>
	`

	m, err := mxj.NewMapXml([]byte(xmlData))
	if err != nil {
		fmt.Println("XML解析错误:", err)
		return
	}

	// 查询所有person的name
	names, err := m.ValuesForKey("name")
	if err != nil {
		fmt.Println("查询错误:", err)
		return
	}

	fmt.Println("所有姓名:")
	for _, name := range names {
		fmt.Println(name)
	}

	// 使用路径查询
	path := "persons.person.#.name"
	values, err := m.ValuesForPath(path)
	if err != nil {
		fmt.Println("路径查询错误:", err)
		return
	}

	fmt.Println("\n通过路径查询的姓名:")
	for _, value := range values {
		fmt.Println(value)
	}
}

高级特性

1. 属性处理

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
)

func main() {
	xmlData := `
		<book id="123">
			<title>Go Programming</title>
			<author>John Doe</author>
		</book>
	`

	m, err := mxj.NewMapXml([]byte(xmlData))
	if err != nil {
		fmt.Println("XML解析错误:", err)
		return
	}

	// 获取属性
	id, err := m.ValueForPath("book.-id")
	if err != nil {
		fmt.Println("获取属性错误:", err)
		return
	}

	fmt.Println("Book ID:", id)
}

2. 自定义XML标签

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
)

func main() {
	jsonData := `{
		"person": {
			"name": "John Doe",
			"age": 30
		}
	}`

	m, err := mxj.NewMapJson([]byte(jsonData))
	if err != nil {
		fmt.Println("JSON解析错误:", err)
		return
	}

	// 自定义根标签
	xmlData, err := m.Xml("customRoot")
	if err != nil {
		fmt.Println("XML转换错误:", err)
		return
	}

	fmt.Println("自定义根标签的XML:")
	fmt.Println(string(xmlData))
}

注意事项

  1. XML转换为JSON时,属性会以"-"为前缀,如-id表示id属性
  2. 数组元素在路径中使用#表示,如persons.person.#.name
  3. 处理大型XML/JSON文件时,考虑使用流式处理方式
  4. 复杂嵌套结构可能需要特殊处理

mxj库提供了丰富的功能来处理XML和JSON数据,通过上述示例,您可以轻松实现两种格式的互转以及复杂的数据查询操作。

回到顶部