XML 发票解析

news2024/12/22 1:51:15

文章目录

  • 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(); // <EInvoice>
        Element eInvoiceData = root.element("EInvoiceData"); // <EInvoiceData>
        // 备注中的销方信息提取
        Element sellerInformation = eInvoiceData.element("SellerInformation"); // <SellerInformation>
        Element sellerBankName = sellerInformation.element("SellerBankName");
        Element sellerBankAccNum = sellerInformation.element("SellerBankAccNum");
        String sellerBankNameValue="";
        String sellerBankAccNumValue="";
        if(sellerBankName!=null){
            sellerBankNameValue = sellerBankName.getTextTrim();//获取<SellerBankName>的文本内容【销方开户银行】
        }
        if(sellerBankAccNum!=null){
            sellerBankAccNumValue = sellerBankAccNum.getTextTrim();//获取<SellerBankAccNum>的文本内容【销方银行账号】
        }
        // 备注中的购方信息提取
        Element buyerInformation = eInvoiceData.element("BuyerInformation"); // <BuyerInformation>
        Element buyerBankName = buyerInformation.element("BuyerBankName");
        Element buyerBankAccNum = buyerInformation.element("BuyerBankAccNum");
        String buyerBankNameValue="";
        String buyerBankAccNumValue="";
        if(buyerBankName!=null){
            buyerBankNameValue = buyerBankName.getTextTrim();//获取<BuyerBankName>的文本内容【购方开户银行】
        }
        if(buyerBankAccNum!=null){
            buyerBankAccNumValue = buyerBankAccNum.getTextTrim();//获取<BuyerBankAccNum>的文本内容【购方银行账号】
        }
        // 开票金额提取
        Element issuItemInformation = eInvoiceData.element("IssuItemInformation"); // <IssuItemInformation>
        Element totalAmount = issuItemInformation.element("TotaltaxIncludedAmount"); // <TotaltaxIncludedAmount>
        String totalAmountValue="";
        if(totalAmount!=null){
            totalAmountValue = totalAmount.getTextTrim();// 获取<TotaltaxIncludedAmount>的文本内容
        }
        // 发票号码
        Element taxSupervisionInfo = root.element("TaxSupervisionInfo"); // <TaxSupervisionInfo>
        Element invoiceNumber = taxSupervisionInfo.element("InvoiceNumber");
        String invoiceNumberValue="";
        if(invoiceNumber!=null){
            invoiceNumberValue = invoiceNumber.getTextTrim();//获取<InvoiceNumber>的文本内容【发票号码】
        }
        //开票日期
        Element issueTime = taxSupervisionInfo.element("IssueTime");
        String issueTimeValue="";
        if(issueTime!=null){
            issueTimeValue = issueTime.getTextTrim();//获取<IssueTime>的文本内容【开票日期】
        }
        //创建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<Object> 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测试结果如下
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1988533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL的简单介绍

文章目录 数据库关系型数据库非关系型数据”数据库的概念和用途MySQL数据库服务器、数据库和表的关系数据库的创建和删除表创建表修改常见的数据类型和约束字符串类型日期和时间类型PRIMARY KEY使用AUTO_INCREMENT使用UNIQUE使用FOREIGN KEY使用 SQL语言基础SQL语言简介SQL分类…

基于Spark的豆瓣书籍推荐系统的设计与实现-计算机毕业设计源码53447

摘要 本论文主要论述了如何基于Spark开发一个豆瓣书籍推荐系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述豆瓣书籍推荐系统的当前背景以及系统开发的目的&#xff0c;后续章节将严…

谷粒商城实战笔记-MySQL踩坑记录

文章目录 1&#xff0c; Public Key Retrieval is not allowed问题描述解决办法 2&#xff0c;1044 -Access denied for user root% to database解决方案 1&#xff0c; Public Key Retrieval is not allowed 问题描述 打开DBeaver连接MySQL提示“Public Key Retrieval is no…

大数据信用报告查询有什么作用?怎么选择查询平台?

随着互联网的快速发展&#xff0c;人们的金融行为越来越多地依赖于网络平台。然而&#xff0c;网络上的金融交易存在着一定的风险&#xff0c;为了有效地防范这些风险&#xff0c;金融机构采用了大数据技术进行风险控制&#xff0c;下面&#xff0c;小易大数据平台将详细介绍大…

20240807 每日AI必读资讯

&#x1f468;‍&#x1f4bc;马斯克再发难、OpenAI 高层巨变&#xff1a;两大核心人物离职&#xff0c;总裁休长假到年底 - OpenAI 联合创始人 John Schulman 官宣离职&#xff0c;加入原是竞品公司的 Anthropic - 陪伴 OpenAI 共同成长 9 年的总裁兼联合创始人 Greg Brockm…

《计算机组成原理》(第3版)第3章 系统总线 复习笔记

第3章 系统总线 一、总线的基本概念 总线是连接多个部件的信息传输线&#xff0c;是各部件共享的传输介质&#xff0c;如图3-1所示。 图3-1 面向CPU的双总线结构框图 倘若将CPU、主存和I/O设备都挂到一组总线上&#xff0c;便形成单总线结构的计算机&#xff0c;如图3-2所示…

【自动驾驶】ubuntu server安装桌面版

目录 安装桌面版当锁屏界面使用root用户登录错误时 这里环境一开始是ubuntu20.04服务器版本 安装桌面版 sudo apt-get update sudo apt-get upgrade apt-get install -y ubuntu-desktop # 如果你不想安装一些附加的程序&#xff0c;可用以下命令 sudo apt install --no-instal…

java创建多线程方式

文章目录 概要继承 Thread 类实现 Runnable 接口实现 Callable 接口线程池 概要 继承 Thread 类 public class Test extends Thread {Overridepublic void run() {System.out.println("current thread is:" Thread.currentThread().getName());}public static voi…

Aigtek超声功率放大器在建筑结构检测中的应用

超声功率放大器是一种可以可放大交、直流信号的功率放大器。它可以用来驱动高压型负载。通过与主流的信号发生器配套使用&#xff0c;实现信号的放大&#xff0c;因此超声功率放大器在建筑结构检测中有着良好应用&#xff0c;今天Aigtek安泰电子就为大家介绍一下。 什么是超声波…

拓普壹老阳:人力rpo项目如何做才会成功?

为了成功执行老阳推荐的人力RPO项目(招聘流程外包)&#xff0c;关键在于几个核心要素的有效整合和执行。RPO项目不仅仅是简单地外包招聘流程&#xff0c;更是通过优化流程、提升效率和质量&#xff0c;帮助企业实现人才招聘的战略目标。 首先&#xff0c;项目的成功与需求分析和…

PID控制算法

关于PID算法最全的文章&#xff01;从浅入深快速掌握 GitHub - br3ttb/Arduino-PID-Library

STM32F28335:按键实验

一个简单的按键实验&#xff1a; 每一个按键的功能是不一样的 其中不知道为什么key3出现了问题&#xff0c;可是查不出原因&#xff0c;就先放在这里了 按键采用行列扫描的方式判断 大家可以自己看资料 看管脚和资料是程序猿的基本功 代码&#xff1a; key的驱动 keys.c…

【Java】Java泛型、集合、UML统一建模语言、final关键字

昨天在昆仑巢&#xff0c;下午练习Spring Boot的过滤器Filter。 昨天傍晚开始阅读《疯狂Java讲义(第2版)》&#xff0c;熟悉了UML建模语言、Final修饰符、List集合和泛型。 1.UML建模语言: 13种图&#xff0c;常用的包括用例图、类图、组件图、部署图、顺序图、活动图和状态机…

【ai】 时间序列分析的python例子

时间序列分析 :分析和理解随时间变化的数据序列 在gcc的趋势滤波后,需要对排队延迟梯度进行检测及调整,参考的是一个阈值, 调整阈值时就使用了时间序列分析技术: 时间序列分析是统计学和数据分析中的一种技术,用于分析和理解随时间变化的数据序列。时间序列数据具有时间上…

活动易企秀H5场景秀源码系统 带完整的安装代码包以及搭建教程

在数字化营销飞速发展的今天&#xff0c;H5页面以其独特的互动性、高度的传播性和良好的兼容性成为众多企业及个人宣传推广的首选。而“活动易企秀H5场景秀”作为一款广受欢迎的在线H5创作工具&#xff0c;凭借其丰富的模板、简易的操作流程&#xff0c;让非技术背景的用户也能…

MySQL笔记(八):事务

一、事务 事务用于保证数据的一致性&#xff0c;它由一组相关的dml组成&#xff0c;该组的dml语句要么全部成功&#xff0c;要么全部失败&#xff1a;转账。 事务和锁&#xff1a;当执行事务操作时&#xff08;dml语句&#xff09;,mysql会在表上加锁&#xff0c;防止其他用户…

【Mysql】第十四章 使用C语言链接(环境配置+连接库+sql函数)

文章目录 1.下载库2.上传库3.编译库4.连接库创建对象-mysql_init连接数据库-mysql_real_connect关闭数据库连接-mysql_close 5.sql函数设置编码格式-mysql_set_character_set发送请求-mysql_query获取查询结果-mysql_store_result获取查询结果的行数-mysql_num_rows获取查询结果…

案例开发-日程管理2第一期(超详细教程、配备图文和源代码注释,没学过也能看懂)

文章目录 一、 项目前期准备1.数据库准备2.导入依赖3.pojo包处理4.dao包处理5.service包处理6.controller包处理7.加密工具类的使用8.页面文件的导入 总结 一、 项目前期准备 1.数据库准备 创建schedule_system数据库并执行如下语句 SET NAMES utf8mb4; SET FOREIGN_KEY_CHE…

国产AI大模型:从萌芽到繁盛,未来可期

I一、AI****大模型的起源 自1950年图灵提出著名的“图灵测试”以来&#xff0c;人工智能领域经历了从学术探索到实际应用的转变。1956年达特茅斯会议上“人工智能”一词的首次提出&#xff0c;标志着AI正式成为学术研究的焦点。进入21世纪&#xff0c;随着计算能力的显著提升和…

【Pyspark-驯化】一文搞懂Pyspark中的withColumnRenamed函数的使用技巧

【Pyspark-驯化】一文搞懂Pyspark中的withColumnRenamed函数的使用技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 相关内容文档获取…