xml通用解析类_Go解决简单问题系列(二)xml处理

简单系列是使用GO语言解决一些业务场景下的实际问题,比如数据处理、文件解析等等,没啥技术含量,不过比较实用。

业务场景

6584fc1686d31ad53e8978616aeca291.png

    前段时间做了很多系统对接的工作,对方提供了input和output的数据下载,但是下载下来的是xml文件,我想要进行解析特定字段并保存到excel中进行处理,要怎么做呢?

解决思路

6584fc1686d31ad53e8978616aeca291.png

    这里需要用的xml解析和上一篇文章中提到的excel生成,如果不清楚go怎么快速操作excel的,可以先看下之前的文章:

Excel处理

Go语言单排,公众号:GO语言单排Go解决简单问题系列(一)-Excel处理

代码实现

6584fc1686d31ad53e8978616aeca291.png

1. 准备工作:

(1)新建一个文件夹xml;

(2)进入xml文件夹;

(3)使用go mod

go mod init xml(这里是你的项目名,用什么都可以)

(4)新建一个main.go的文件;

(5)下载类库tealeg/xlsx(用来处理excel的文件),而xml的处理交给了基本库中的`encoding/xml`。

    整体的目录结构非常简单,如下图所示,这也是我们使用go而不是java进行处理的原因。java过于重量级,这种简单的事情还是交给go吧

3e3bb942aa04c456284c0d0baa7dc0bd.png

图1. 目录结构

2. 代码:

    放代码之前,先和大家说下xml的两种处理逻辑。

67fe8250f457c4b42184750ee5f06db1.png

图2. 一个简单的xml(部分)

    (1)定义结构体进行存储。由于xml是类json的结构,有着严格的起始和终止符,因此我们可以定义一个结构体,将xml的数据存进去。不过在实际操作中,我定义结构体之后xml的数据始终没有正确存入,因此我选择了第二种相对复杂的处理方式。

    (2)遍历。对xml的数据进行遍历,根据类型不同可以进行判断,其类型主要包括:元素开始标记、元素结束标记和字符数据。前两个是标签,最后一个才是我们最终要解析的字段。

package mainimport (  "bytes"  "encoding/xml"  "fmt"  "io/ioutil"  "log"  "os"  "strconv"  "strings"  "github.com/tealeg/xlsx")// 定义了一个结构体来进行相应存储type Expense struct {  BOOK_AMOUNT     []string  TAX_FREE_AMOUNT []string  TAX_AMOUNT      []string}func main() {  // 从文件读取,如可以如下:  content, _ := ioutil.ReadFile("220.xml")  decoder := xml.NewDecoder(bytes.NewBuffer(content))  expenses := construct(decoder)  exportExcel("demo.xlsx", expenses)}// 解析xmlfunc construct(decoder *xml.Decoder) Expense {  var (    expense Expense    t       xml.Token    err     error  )  // 定义了几个数组,用来存储遍历后各个字段的值,一会儿存入excel中  var bookAmount []string  var taxFreeAmount []string  var taxAmount []string  var name string  for t, err = decoder.Token(); err == nil; t, err = decoder.Token() {    switch token := t.(type) {    // 处理元素开始(标签) - 这个标签我暂时用不到    case xml.StartElement:      name = token.Name.Local      fmt.Printf("Token name: %s\n", name)      for _, attr := range token.Attr {        attrName := attr.Name.Local        attrValue := attr.Value        fmt.Printf("An attribute is: %s %s\n", attrName, attrValue)      }    // 处理元素结束(标签) - 这个标签我暂时也用不到    case xml.EndElement:      fmt.Printf("Token of '%s' end\n", token.Name.Local)    // 处理字符数据(这里就是元素的文本) - 这里是重点    // 获取字段的key和value,进行对应的存储    case xml.CharData:      content := string([]byte(token))      if name == "BOOK_AMOUNT" {        bookAmount = append(bookAmount, content)      }      if name == "TAX_FREE_AMOUNT" {        taxFreeAmount = append(taxFreeAmount, content)      }      if name == "TAX_AMOUNT" {        taxAmount = append(taxAmount, content)      }      fmt.Printf("This is the content: %v\n", content)    }  }  // 将数组存入结构体中  expense.BOOK_AMOUNT = bookAmount  expense.TAX_FREE_AMOUNT = taxFreeAmount  expense.TAX_AMOUNT = taxAmount  return expense}// 根据文件名获取文件路径 - 通用方法func getFilePath(fileName string) string {  dir, err := os.Getwd()  if err != nil {    log.Fatal(err)  }  return dir + "\\" + fileName}// 生成excel - 通用方法func exportExcel(fileName string, expense Expense) {  outFile := getFilePath(fileName)  file := xlsx.NewFile()  sheet, err := file.AddSheet("result_sheet")  if err != nil {    fmt.Print(err)  }  bookAmount := expense.BOOK_AMOUNT  taxFreeAmount := expense.TAX_FREE_AMOUNT  taxAmount := expense.TAX_AMOUNT  // 添加表头  row := sheet.AddRow()  for i := 0; i < 3; i++ {    nameCell := row.AddCell()    switch i {    case 0:      nameCell.SetValue("总额")    case 1:      nameCell.SetValue("不含税")    case 2:      nameCell.SetValue("税额")    }  }  for i, v := range bookAmount {    if strings.Contains(v, "\n") {      continue    }    row := sheet.AddRow()    v1 := taxFreeAmount[i]    v2 := taxAmount[i]    for j := 0; j < 3; j++ {      nameCell := row.AddCell()      switch j {      case 0:        vtemp, _ := strconv.ParseFloat(v, 64)        nameCell.SetFloat(vtemp)      case 1:        v1temp, _ := strconv.ParseFloat(v1, 64)        nameCell.SetFloat(v1temp)      case 2:        v2temp, _ := strconv.ParseFloat(v2, 64)        nameCell.SetFloat(v2temp)      }    }  }  err = file.Save(outFile)  if err != nil {    fmt.Println(err)  }

    下图是解析完成后生成的excel,因为数据涉及金额,所以我做了处理。

60c1d5084bf27a7f53a57f68a8a87839.png

图3. 生成的excel

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值