码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • XML 发票解析


    文章目录

    • 1. xml 类型发票格式
    • 2. 数据提取思路
      • 2.1 项目结构
    • 3. 提取实现
      • 3.1 实体类
      • 3.2 提取工具类
      • 3.3 controller
      • 3.4 service
    • 4. 结果展示

    1. xml 类型发票格式

    本文解析的xml类型的发票格式如下
    在这里插入图片描述

    2. 数据提取思路

    通过遍历xml文件中的标签去获得标签对应的文本

    2.1 项目结构

    在这里插入图片描述

    3. 提取实现

    3.1 实体类

    Invoice

    package com.example.xml.entity;
    
    import lombok.Data;
    
    import java.util.Date;
    
    @Data
    public class Invoice {
        private String invoiceNumber; // 发票号码
        private Date invoiceDate; // 开票日期
        private String totalAmount;// 总开票金额
        private String invoiceRemarks;// 发票备注
    }
    
    

    3.2 提取工具类

    package com.example.xml.utils;
    
    import com.example.xml.entity.Invoice;
    import org.dom4j.io.SAXReader;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.springframework.web.multipart.MultipartFile;
    
    public class XmlUtils {
        /**
         * 调用该方法将前端接受到的文件暂存
         *
         * @param file
         */
        public static Invoice parseXmlFile(MultipartFile file) {
            Invoice invoice = new Invoice();
            File tempFilePath=null;
            try {
                // 创建一个临时文件
                Path tempFile = null;
                tempFile = Files.createTempFile("tempPrefix", ".xml");
    
                tempFilePath = tempFile.toFile();
    
                // 将MultipartFile的内容写入到临时文件
                try (FileOutputStream fos = new FileOutputStream(tempFilePath)) {
                    fos.write(file.getBytes());
                }
    
                // 使用临时文件的路径来调用你的解析方法
                invoice = extract(tempFilePath);
    
                // 删除临时文件,或者在某些情况下保留它
    //            tempFilePath.delete();
    
            } catch (Exception e) {
                // 处理异常
                e.printStackTrace();
            }finally {
                // 无论是否发生异常,都尝试删除临时文件
                if (tempFilePath != null && !tempFilePath.delete()) {
                    // 记录删除失败的情况
                    System.err.println("无法删除临时文件: " + tempFilePath.getAbsolutePath());
                }
            }
            // 返回值
            return invoice;
        }
    
        /**
         * 从一个ZIP 文件中提取特定格式的发票信息,并构建一个 Invoice 对象来存储这些信息
         *
         * @param file
         * @return
         * @throws IOException
         * @throws DocumentException
         */
        public static Invoice extract(File file) throws DocumentException, ParseException {
            Invoice invoice = new Invoice();//创建发票实例
            SAXReader reader = new SAXReader();
            Document document = reader.read(file);// 读取XML文件
            // 获取备注中的部分信息
            Element root = document.getRootElement(); // 
            Element eInvoiceData = root.element("EInvoiceData"); // 
            // 备注中的销方信息提取
            Element sellerInformation = eInvoiceData.element("SellerInformation"); // 
            Element sellerBankName = sellerInformation.element("SellerBankName");
            Element sellerBankAccNum = sellerInformation.element("SellerBankAccNum");
            String sellerBankNameValue="";
            String sellerBankAccNumValue="";
            if(sellerBankName!=null){
                sellerBankNameValue = sellerBankName.getTextTrim();//获取的文本内容【销方开户银行】
            }
            if(sellerBankAccNum!=null){
                sellerBankAccNumValue = sellerBankAccNum.getTextTrim();//获取的文本内容【销方银行账号】
            }
            // 备注中的购方信息提取
            Element buyerInformation = eInvoiceData.element("BuyerInformation"); // 
            Element buyerBankName = buyerInformation.element("BuyerBankName");
            Element buyerBankAccNum = buyerInformation.element("BuyerBankAccNum");
            String buyerBankNameValue="";
            String buyerBankAccNumValue="";
            if(buyerBankName!=null){
                buyerBankNameValue = buyerBankName.getTextTrim();//获取的文本内容【购方开户银行】
            }
            if(buyerBankAccNum!=null){
                buyerBankAccNumValue = buyerBankAccNum.getTextTrim();//获取的文本内容【购方银行账号】
            }
            // 开票金额提取
            Element issuItemInformation = eInvoiceData.element("IssuItemInformation"); // 
            Element totalAmount = issuItemInformation.element("TotaltaxIncludedAmount"); // 
            String totalAmountValue="";
            if(totalAmount!=null){
                totalAmountValue = totalAmount.getTextTrim();// 获取的文本内容
            }
            // 发票号码
            Element taxSupervisionInfo = root.element("TaxSupervisionInfo"); // 
            Element invoiceNumber = taxSupervisionInfo.element("InvoiceNumber");
            String invoiceNumberValue="";
            if(invoiceNumber!=null){
                invoiceNumberValue = invoiceNumber.getTextTrim();//获取的文本内容【发票号码】
            }
            //开票日期
            Element issueTime = taxSupervisionInfo.element("IssueTime");
            String issueTimeValue="";
            if(issueTime!=null){
                issueTimeValue = issueTime.getTextTrim();//获取的文本内容【开票日期】
            }
            //创建Invoice实例,并填充发票信息
            if (invoiceNumberValue != null && invoiceNumberValue != "") {//发票号码
                invoice.setInvoiceNumber(invoiceNumberValue);
            }
            if (issueTimeValue != null && issueTimeValue != "") {//开票日期
                SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                Date parsedDate = inputDateFormat.parse(issueTimeValue);
                invoice.setInvoiceDate(parsedDate);
            }
            if (totalAmountValue != null && totalAmountValue != "") {// 开票金额
                invoice.setTotalAmount(totalAmountValue);
            }
            //在设置之前排好发票备注的版型
            String note = setNote(buyerBankNameValue, buyerBankAccNumValue, sellerBankNameValue, sellerBankAccNumValue);
            invoice.setInvoiceRemarks(note);
    
    
            return invoice;
        }
    
        /**
         * 拼接备注信息
         *
         * @param buyerBankNameValue    购方开户银行
         * @param buyerBankAccNumValue  购方银行账号
         * @param sellerBankNameValue   销方开户银行
         * @param sellerBankAccNumValue 销方银行账号
         * @return
         */
        public static String setNote(String buyerBankNameValue, String buyerBankAccNumValue, String sellerBankNameValue, String sellerBankAccNumValue) {
            String resultNote = "";
            if (buyerBankNameValue != null && buyerBankNameValue != "") {
                resultNote += "购方开户银行:" + buyerBankNameValue + ";";
            }
            if (buyerBankAccNumValue != null && buyerBankAccNumValue != "") {
                resultNote += "银行账号:" + buyerBankAccNumValue + ";";
            }
            if (sellerBankNameValue != null && sellerBankNameValue != "") {
                resultNote += "销方开户银行:" + sellerBankNameValue + ";";
            }
            if (sellerBankAccNumValue != null && sellerBankAccNumValue != "") {
                resultNote += "银行账号:" + sellerBankAccNumValue + ";";
            }
    
            return resultNote;
        }
    
    }
    
    

    3.3 controller

    package com.example.xml.controller;
    
    import com.example.xml.entity.Invoice;
    import com.example.xml.service.InvoiceService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    
    @RestController
    @RequestMapping("/invoice")
    public class InvoiceController {
        @Autowired
        InvoiceService invoiceService;
    
        /**
         * @param
         */
        @CrossOrigin(origins = "http://localhost:8081", allowedHeaders = "*", allowCredentials = "true")
        @PostMapping("/upload")
        public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
            try {
                // 调用你的文件解析服务
                Invoice parsedData = invoiceService.parseOfdFile(file);
    
                // 返回解析后的数据
                return ResponseEntity.ok(parsedData);
            } catch (Exception e) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error parsing file");
            }
        }
    }
    
    

    3.4 service

    InvoiceService

    package com.example.xml.service;
    
    import com.example.xml.entity.Invoice;
    import org.springframework.web.multipart.MultipartFile;
    
    public interface InvoiceService {
        Invoice parseOfdFile(MultipartFile file);
    
    }
    
    

    InvoiceServiceImpl

    package com.example.xml.service.impl;
    
    
    import com.example.xml.entity.Invoice;
    import com.example.xml.service.InvoiceService;
    import com.example.xml.utils.XmlUtils;
    import org.springframework.stereotype.Service;
    import org.springframework.web.multipart.MultipartFile;
    
    @Service
    public class InvoiceServiceImpl implements InvoiceService {
        @Override
        public Invoice parseOfdFile(MultipartFile file) {
            Invoice invoice = XmlUtils.parseXmlFile(file);
            return invoice;
        }
    }
    
    

    4. 结果展示

    postman测试结果如下
    在这里插入图片描述

  • 相关阅读:
    最新下载:Paragon NTFS for Mac 15【软件附加安装教程】
    m3u8,rtsp,rtmp,flv,mp4直播流在线测试地址(2022年8月)
    机器学习实战-支持向量机
    做了2年“手工测试”,想自学自动化测试,过来人给的一些学习技巧
    学习open62541 ---[68] 使用Wireshark观察通信消息
    【论文阅读笔记】-针对RSA的短解密指数的密码学分析(Cryptanalysis of Short RSA Secret Exponents)
    SpringBoot--@InitBinder--使用/原理
    软考 系统架构设计师 简明教程 | 软件开发方法
    基于左序遍历的数据存储实践
    霸榜双11!科技创新助力九牧卫浴赢战全渠道
  • 原文地址:https://blog.csdn.net/weixin_43866613/article/details/140991414
    • 最新文章
    • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
      用 Hashids 优雅解决 C 端自增 ID 暴露问题
      V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
      LLVM Pass快速入门(四):代码插桩
      milkup:桌面端 markdown AI续写和即时渲染
      基于项目工程构建SBOM(软件物料清单)的研究
      鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
      .NET 中如何快速实现 List 集合去重?
      扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
      浅谈数据访问层
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    小工具 小游戏
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

    京公网安备 11010502049817号