ofd 文件发票解析

一、OFD

OFD(Open Fixed-layout Document) ,是由工业和信息化部软件司牵头中国电子技术标准化研究院成立的版式编写组制定的版式文档国家标准,属于中国的一种自主格式,要打破政府部门和党委机关电子公文格式不统一,以方便地进行电子文档的存储、读取以及编辑。

二、OFD格式发票解析

ofd文件类似与zip,解析思路是将其解压之后,然后对其中的xml文件进行处理,可以用dom4j,根据需要选择要处理的xml

OFD.XML

<?xml version="1.0" encoding="UTF-8"?>

-<ofd:OFD Version="1.1" DocType="OFD" xmlns:ofd="http://www.ofdspec.org/2016">


-<ofd:DocBody>


-<ofd:DocInfo>

<ofd:DocID>605a0643270f4874b54b541369ea24f7</ofd:DocID>

<ofd:Author>China Tax</ofd:Author>

<ofd:CreationDate>2020-09-10</ofd:CreationDate>


-<ofd:CustomDatas>

<ofd:CustomData Name="template-version">1.0.20.0422</ofd:CustomData>

<ofd:CustomData Name="native-producer">SuwellFormSDK</ofd:CustomData>

<ofd:CustomData Name="producer-version">1.0.20.0603</ofd:CustomData>

<ofd:CustomData Name="发票代码">033022000313</ofd:CustomData>

<ofd:CustomData Name="发票号码">00000001</ofd:CustomData>

<ofd:CustomData Name="合计税额">11283.71</ofd:CustomData>

<ofd:CustomData Name="合计金额">86797.75</ofd:CustomData>

<ofd:CustomData Name="开票日期">2020年09月01日</ofd:CustomData>

<ofd:CustomData Name="校验码">11058 76307 04808 54113</ofd:CustomData>

<ofd:CustomData Name="购买方纳税人识别号">913302127995019136</ofd:CustomData>

<ofd:CustomData Name="销售方纳税人识别号">91330203MA2H7WU45J</ofd:CustomData>

</ofd:CustomDatas>

</ofd:DocInfo>

<ofd:DocRoot>Doc_0/Document.xml</ofd:DocRoot>

<ofd:Signatures>Doc_0/Signs/Signatures.xml</ofd:Signatures>

</ofd:DocBody>

</ofd:OFD>

original_invoice.xml

<?xml version="1.0" encoding="UTF-8"?>

-<eInvoice Version="1.0" xmlns:fp="http://www.edrm.org.cn/schema/e-invoice/2019">

<fp:DocID>03</fp:DocID>

<fp:InvoiceCode>033022000313</fp:InvoiceCode>

<fp:InvoiceNo>00000001</fp:InvoiceNo>

<fp:TypeCode>0</fp:TypeCode>

<fp:IssueDate>2020年09月01日</fp:IssueDate>

<fp:InvoiceCheckCode>11058763070480854113</fp:InvoiceCheckCode>

<fp:MachineNo>667900296527</fp:MachineNo>

<fp:TaxControlCode>00945*1<0-3>2*62377>93158<5< <4024141+0091580+/30920879<8 4+3-*<3><21/723494/+/+01+225 0*6220933>43/501+<>71+>>><7/ </fp:TaxControlCode>


-<fp:Buyer>

<fp:BuyerName>雅戈尔服装控股有限公司</fp:BuyerName>

<fp:BuyerTaxID>913302127995019136</fp:BuyerTaxID>

<fp:BuyerAddrTel>宁波市海曙区鄞县大道西段2号0574-87425577</fp:BuyerAddrTel>

<fp:BuyerFinancialAccount>农行宁波雅戈尔分理处39428001040000723</fp:BuyerFinancialAccount>

</fp:Buyer>

<fp:Tpvn/>


-<fp:Seller>

<fp:SellerName>宁波狮丹努创客科贸有限公司</fp:SellerName>

<fp:SellerTaxID>91330203MA2H7WU45J</fp:SellerTaxID>

<fp:SellerAddrTel>浙江省宁波市海曙区吴家路83号1-987457828</fp:SellerAddrTel>

<fp:SellerFinancialAccount>宁波银行海曙支行20010122000732464</fp:SellerFinancialAccount>

<fp:Issuea1/>

<fp:Issuea2/>

</fp:Seller>

<fp:TaxInclusiveTotalAmount>98081.46</fp:TaxInclusiveTotalAmount>

<fp:Note/>

<fp:InvoiceClerk>管理员</fp:InvoiceClerk>

<fp:Payee>管理员</fp:Payee>

<fp:Checker>管理员</fp:Checker>

<fp:TaxTotalAmount>11283.71</fp:TaxTotalAmount>

<fp:TaxExclusiveTotalAmount>86797.75</fp:TaxExclusiveTotalAmount>

<fp:GraphCode>01,20,033022000313,00000001,86797.75,20200901,11058763070480854113,BCB8,</fp:GraphCode>

<fp:InvoiceSIA1/>

<fp:InvoiceSIA2/>

<fp:Signature>MIIBBQYKKoEcz1UGAQQCAqCB9jCB8wIBATEOMAwGCCqBHM9VAYMRBQAwDAYKKoEcz1UGAQQCATGBzzCBzAIBATBjMFgxCzAJBgNVBAYTAkNOMRswGQYDVQQLDBLlm73lrrbnqI7liqHmgLvlsYAxLDAqBgNVBAMMI+eojuWKoeeUteWtkOivgeS5pueuoeeQhuS4reW/gyhTTTIpAgdEAwAAATl1MAwGCCqBHM9VAYMRBQAwDAYIKoEcz1UBg3UFAARGMEQCIGROWCbe2SVfGU8rXl9DTutArClYOxNJVt2bu6RMBW/PAiBoYhg/z8uTptlM+3Qqs1FUMxn37Puo4ii4TLdD+ah+cw==</fp:Signature>


-<fp:GoodsInfos>


-<fp:GoodsInfo>

<fp:Item>*纺织产品*200g/m2 100%羊毛1*1罗纹</fp:Item>

<fp:Specification>262815-6557</fp:Specification>

<fp:MeasurementDimension>KG</fp:MeasurementDimension>

<fp:Price>267.070006807352</fp:Price>

<fp:Quantity>325</fp:Quantity>

<fp:Amount>86797.75</fp:Amount>

<fp:TaxScheme>13%</fp:TaxScheme>

<fp:TaxAmount>11283.71</fp:TaxAmount>

</fp:GoodsInfo>

</fp:GoodsInfos>

</eInvoice>




import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.data.model.Invoice;

/**
 * 
 * 发票ofd解析util.<br>
 * 
 * @author qianxiangyun <br>
 * @version 1.0.0 2021年7月13日<br>
 * @see
 * @since JDK 1.5.0
 */
public final class InvoiceOfdUtil {
	/**
	 * 构造方法.
	 */
	private InvoiceOfdUtil() {

	}

	/**
	 * 日期格式化.
	 */
	static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日"); // 注意月份是MM

	public static void main(final String[] args) {
		// 1.解压ofd文件
		try {
			final String xmlPath = unzip("C:\\Users\\qxy\\Desktop\\033022000313_00000001.ofd");
			final SAXReader reader = new SAXReader();
			Document doc;
			try {
				doc = reader.read(new File(xmlPath));
				final Element rootElement = doc.getRootElement(); // 获取document对象根节点,即最外层节点下的内容
				// 发票代码、发票号码、
				Invoice invoice = new Invoice();
				invoice = generateInvoice(rootElement, invoice);
				System.out.println(invoice.getInvoiceCode());
			} catch (DocumentException e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * ofd发票文件解析.
	 * @param filePath filePath
	 * @return Invoice
	 */
	public static Invoice parseOfd(final String filePath) {
		// 发票代码、发票号码、
		Invoice invoice = new Invoice();
		try {
			final String xmlPath = unzip(filePath);
			final SAXReader reader = new SAXReader();
			Document doc;
			try {
				doc = reader.read(new File(xmlPath));
				final Element rootElement = doc.getRootElement(); // 获取document对象根节点,即最外层节点下的内容

				invoice = generateInvoice(rootElement, invoice);
				System.out.println(invoice.getInvoiceCode());
			} catch (DocumentException e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return invoice;
	}
	/**
	 * 生成发票信息.
	 * @param rootElement rootElement
	 * @param invoice invoice
	 * @return Invoice
	 */
	private static Invoice generateInvoice(final Element rootElement, final Invoice invoice) {
		// 发票代码
		final Element invoiceCodeElement = rootElement.element("InvoiceCode");
		// 发票号码
		final Element invoiceNoElement = rootElement.element("InvoiceNo");
		// 开票日期
		final Element issueDateElement = rootElement.element("IssueDate");
		// 校验码
		final Element invoiceCheckCodeElement = rootElement.element("InvoiceCheckCode");
		// 机器编号
		final Element machineNoElement = rootElement.element("MachineNo");
		// 密码区
		final Element taxControlCodeElement = rootElement.element("TaxControlCode");
		// 购买方
		final Element buyerElement = rootElement.element("Buyer");
		// 销售方
		final Element sellerElement = rootElement.element("Seller");
		// 税额
		final Element taxTotalAmountElement = rootElement.element("TaxTotalAmount");
		// 金额
		final Element taxExclusiveTotalAmountElement = rootElement.element("TaxExclusiveTotalAmount");
		// 价税合计
		final Element taxInclusiveTotalAmountElement = rootElement.element("TaxInclusiveTotalAmount");
		// 收款人
		final Element payeeElement = rootElement.element("payee");
		// 开票人
		final Element invoiceClerkElement = rootElement.element("InvoiceClerk");
		// 复核
		final Element checkerElement = rootElement.element("Checker");
		if (invoiceCodeElement != null) {
			invoice.setInvoiceCode(invoiceCodeElement.getText());
		}
		if (invoiceNoElement != null) {
			invoice.setInvoiceNumber(invoiceNoElement.getText());
		}
		if (issueDateElement != null && issueDateElement.getText() != null) {
			Date date = null;
			try {
				date = simpleDateFormat.parse(issueDateElement.getText());
			} catch (ParseException e) {
				e.printStackTrace();
			}
			invoice.setBillingDate(date);
		}
		if (invoiceCheckCodeElement != null) {
			invoice.setCheckCode(invoiceCheckCodeElement.getText());
		}
		if (machineNoElement != null) {
			invoice.setMachineCode(machineNoElement.getText());
		}
		if (taxControlCodeElement != null) {
			invoice.setMmq(taxControlCodeElement.getText());
		}
		if (buyerElement != null) {
			final List<Element> buyerName = buyerElement.elements("BuyerName");
			final List<Element> buyerTaxID = buyerElement.elements("BuyerTaxID");
			final List<Element> buyerAddrTel = buyerElement.elements("BuyerAddrTel");
			final List<Element> buyerFinancialAccount = buyerElement.elements("BuyerFinancialAccount");
			invoice.setPurchaserName(buyerName.get(0).getText());
			invoice.setPurchaserTaxNo(buyerTaxID.get(0).getText());
			invoice.setPurchaserAddressPhone(buyerAddrTel.get(0).getText());
			invoice.setPurchaserBank(buyerFinancialAccount.get(0).getText());
		}
		if (sellerElement != null) {
			final List<Element> sellerName = sellerElement.elements("SellerName");
			final List<Element> sellerTaxID = sellerElement.elements("SellerTaxID");
			final List<Element> sellerAddrTel = sellerElement.elements("SellerAddrTel");
			final List<Element> sellerFinancialAccount = sellerElement.elements("SellerFinancialAccount");
			invoice.setSalesName(sellerName.get(0).getText());
			invoice.setSalesTaxNo(sellerTaxID.get(0).getText());
			invoice.setSalesAddressPhone(sellerAddrTel.get(0).getText());
			invoice.setSalesBank(sellerFinancialAccount.get(0).getText());
		}
		if (taxTotalAmountElement != null) {
			invoice.setTotalTax(new BigDecimal(taxTotalAmountElement.getText()));
		}
		if (taxExclusiveTotalAmountElement != null) {
			invoice.setTotalAmount(new BigDecimal(taxExclusiveTotalAmountElement.getText()));
		}
		if (taxInclusiveTotalAmountElement != null) {
			invoice.setTotalAmount(new BigDecimal(taxInclusiveTotalAmountElement.getText()));
		}
		if (payeeElement != null) {
			invoice.setSkr(payeeElement.getText());
		}
		if (invoiceClerkElement != null) {
			invoice.setKpr(invoiceClerkElement.getText());
		}
		if (checkerElement != null) {
			invoice.setFh(checkerElement.getText());
		}
		return invoice;
	}

	/**
	 * 从字节流写到文件中.
	 * 
	 * @param is
	 *            流
	 * @return file
	 */
	private static File getFileByBytes(final InputStream is, final String fileName, final String oldFileName) {
		final String tempPath = System.getProperty("java.io.tmpdir");
		final File dirFile = new File(tempPath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}
		final File file = new File(dirFile, fileName); // zip文件需临时存放服务器
		final File oldFile = new File(dirFile, oldFileName);
		OutputStream os = null;
		try {
			if (!file.exists()) {
				file.createNewFile();
			} else {
				file.delete();
				file.createNewFile();
			}
			if (oldFile.exists()) {
				file.delete();
			}
			os = new FileOutputStream(file);
			int len;
			final byte[] buffer = new byte[4096];
			while ((len = is.read(buffer)) != -1) {
				os.write(buffer, 0, len);
			}
			os.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (os != null) {
					os.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return file;
	}
	/**
	 * 解压ofd文件.
	 * @param ofdFile ofdFile
	 * @return ofdFile路径
	 * @throws IOException IOException
	 */
	public static String unzip(final String ofdFile) throws IOException {
		final ZipFile zipFile = new ZipFile(ofdFile);
		String lastFileName = "";
		String temp = "";
		// 循环查找文件
		final Enumeration entries = zipFile.entries();
		while (entries.hasMoreElements()) {
			final ZipEntry zipEntry = (ZipEntry) entries.nextElement();
			if (!zipEntry.isDirectory()) {
				String fileFullName = zipEntry.getName();
				// 若当前文件包含文件夹名称,则直接去文件名称
				if (fileFullName.indexOf("/") != -1 && fileFullName.indexOf("original_invoice") > -1) {
					fileFullName = fileFullName.substring(fileFullName.lastIndexOf("/") + 1);
					lastFileName = fileFullName;
					final InputStream in = zipFile.getInputStream(zipEntry);
					final File xmlfile = getFileByBytes(in, fileFullName, lastFileName);
					temp = xmlfile.toString();
				}
			}
		}
		zipFile.close();
		return temp;
	}
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: PDF(Portable Document Format,便携式文档格式)和OFD(Open Financial Document,开放金融文件格式)都是电子发票的常用格式之一。电子发票作为一种重要的财务凭证,具有便捷性和环保性等优点。因此,对于电子发票格式的解析是非常重要的。 PDF格式的电子发票可以通过Adobe Acrobat等软件进行打开和编辑,它有良好的兼容性和可靠性。同时,PDF格式还可以通过数字签名等方式进行安全加密和验证。 OFD格式的电子发票是一种由中国金融信息标准化技术委员会制定的标准格式,它具有大容量、高效率、安全可靠的优点。与PDF相比,OFD可以实现更多的业务流程和管理需求,得到了越来越广泛的应用。 在解析电子发票的过程中,需要注意格式的兼容性和安全性。同时,需要对发票的内容进行验证和解析,以确保其真实性和合法性。随着电子商务和数字化技术的不断发展,电子发票的标准化和规范化将成为未来的趋势,电子发票解析和管理也将变得更加智能和高效。 ### 回答2: PDF电子发票OFD电子发票均属于电子发票的一种格式,它们都具有可存储、可传递等特点,已经得到广泛应用。因其具有数字化、自动化、便捷性及环保节能等优势,已成为现代电子商务的重要组成部分。 在解析PDF和OFD电子发票时,首先需要理解其文档结构和数据格式。PDF在文件头部和尾部均应当有%%EOF标识,以此表示其为PDF文件,其结构包括文档信息、对象结构、交叉引用表、加密和压缩信息等。OFD则采用XML文档格式,由多个层级的节点组成。OFD采用标准的XML语法,其中包含了发票的开具机构、收款方、明细、税费等信息,信息结构清晰且易于解析解析PDF和OFD电子发票时需要使用相应的解析工具,常见的有PDFBox、iText、OFD Reader等工具。这些工具可以帮助我们解析电子发票中的文本、图片、表格等元素,从而将其转化为可读性强、易于处理的数据格式。 综上所述,PDF和OFD电子发票解析是一项重要的技术,对于电子商务及电子发票的推广普及有着至关重要的作用。随着技术的进步和应用的推广,我们相信PDF和OFD电子发票解析也会得到更好的发展和应用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值