当前位置: 首页 > 知识库问答 >
问题:

APACHE POI EXCEL XmlException:是无效的XML字符,是否有任何方法预处理EXCEL文件?

匡安宜
2023-03-14

我使用java和Apache POI进行阅读。xlsx文件。(6万行),但我得到了错误。

我使用poi和xmlbeans的最新版本maven插件。

根据我在StackOverflow中发现的相关问题,最新的poi应该能够成功地处理具有特殊字符的文件。

如果是xml文件,我可以自己替换程序中的特殊字符。但它是一个excel文件。

困难在于我不知道如何使用poi成功读取“excel”文件。

或者有什么方法可以处理文件?

我使用openjdk,版本:"1.8.0_171-1-redhat"。

像这样的错误消息

Caused by: java.io.IOException: unable to parse shared strings table
    at org.apache.poi.xssf.model.SharedStringsTable.readFrom(SharedStringsTable.java:134)
    at org.apache.poi.xssf.model.SharedStringsTable.<init>(SharedStringsTable.java:111)
    ... 11 more
Caused by: org.apache.xmlbeans.XmlException: error: Character reference "&#55357" is an invalid XML character.
    at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3440)
    at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1272)
    at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1259)
    at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument$Factory.parse(Unknown Source)
    at org.apache.poi.xssf.model.SharedStringsTable.readFrom(SharedStringsTable.java:123)

代码

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import org.apache.commons.codec.binary.Base64;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class test2 {

  public static void main(String[] args) throws Exception {
    File file = new File("D:\\Users\\3389\\Desktop\\Review\\drive-download-20181112T012605Z-001\\ticket.xlsx");
    Workbook workbook = null;
    XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file); //error occured
    workbook = new SXSSFWorkbook(xssfWorkbook);
    Sheet sheet = xssfWorkbook.getSheetAt(0);  
    System.out.println("the first row:"+sheet.getFirstRowNum());
  }
}

pom.xml

        <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi</artifactId>
          <version>4.0.0</version>
        </dependency>
        <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi-ooxml</artifactId>
          <version>4.0.0</version>
        </dependency> 

共享字符串中包含UTF16SURROKEPTAIRS。xml(几个示例

&#55357;&#56397;&#55357;&#56397;&#55357;&#56397;
&#55357;&#56397;
&#55357;&#56397;&#55357;&#56397;&#55357;&#56397;&#55357;&#56397;&#55357;&#56397;&#55357;&#56397;&#55357;&#56397;
etc....

共有1个答案

钮出野
2023-03-14

由于您的问题标题包含问题“是否有任何方法可以预处理excel文件?”,我将尝试回答这个问题:

假设:*. xlsx文件中的/xl/share dStrings.xml包含UTF-16-surrogate对XML数字字符引用,如

因此,如果共享字符串。xml*。xlsx文件包含UTF-16代理项对XML数字字符引用,则该文件已损坏,无论如何都不应使用。这个问题应该由创建该代码的人来解决。xlsx文件。

但是,如果仍然需要修复该文件,那么这只能在字符串级别上完成。由于UTF-16代理项对XML数字字符引用,无法解析XML。然后需要获得共享字符串。xml超出了*。xlsx文件。然后获取该共享字符串的字符串内容。xml文件。然后将找到的每个UTF-16代理项对XML数字字符引用替换为其Unicode替换。

我的代码展示了如何使用java.util.regex.Matcher执行此操作。它搜索与模式匹配的实体

import java.io.*;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import java.util.regex.Pattern; 
import java.util.regex.Matcher;

public class XSSFWrongXMLinSharedStrings {

 static String replaceUTF16SurrogatePairs(String string) {
  Pattern pattern = Pattern.compile("&#(\\d{5});&#(\\d{5});");
  Matcher matcher = pattern.matcher(string);
  while (matcher.find()) {
   String found = matcher.group();
   int h = Integer.valueOf(matcher.group(1));
   int l = Integer.valueOf(matcher.group(2));
   if (0xD800 <= h && h < 0xDC00 && 0xDC00 <= l && l < 0xDFFF) {
    int n = (h - 0xD800) * 0x400 + (l - 0xDC00) + 0x10000;
System.out.print(found + " will be replaced with ");
System.out.println("&#" + n + ";");
    string = string.replace(found, "&#" + n + ";");
   }
  }
  pattern = Pattern.compile("&#(\\d{5});");
  matcher = pattern.matcher(string);
  while (matcher.find()) {
   String found = matcher.group();
   int n = Integer.valueOf(matcher.group(1));
   if (0xD800 <= n && n < 0xDFFF) {
System.out.println(found + " is single part of supplement pair. It will be removed.");
    string = string.replace(found, "");
   }
  }  
  return string;
 }

 public static void main(String[] args) throws Exception {
  File file = new File("ticket.xlsx");

  //Repairing the /xl/sharedStrings.xml on string level. Parsing XML is not possible because of the UTF-16-surrogate-pair XML numeric character references.
  OPCPackage opcPackage = OPCPackage.open(file);
  PackagePart packagePart = opcPackage.getPartsByName(Pattern.compile("/xl/sharedStrings.xml")).get(0);
  ByteArrayOutputStream sharedStringsBytes = new ByteArrayOutputStream();
  byte[] buffer = new byte[1024];
  int length;
  InputStream inputStream = packagePart.getInputStream();
  while ((length = inputStream.read(buffer)) != -1) {
   sharedStringsBytes.write(buffer, 0, length);
  }
  inputStream.close();
  String sharedStrings = sharedStringsBytes.toString("UTF-8");

  //Replace UTF-16-surrogate-pair XML numeric character reference with it's unicode replacement:
  //sharedStrings = sharedStrings.replace("&#55357;&#56833;", "&#x1F601;");
  //ToDo: Create method for replacing all possible UTF-16-surrogate-pair XML numeric character references with their unicode replacements.
  sharedStrings = replaceUTF16SurrogatePairs(sharedStrings);

  OutputStream outputStream = packagePart.getOutputStream();
  outputStream.write(sharedStrings.getBytes("UTF-8"));
  outputStream.flush();
  outputStream.close();
  opcPackage.close();
  //Now the /xl/sharedStrings.xml in the file does not contain UTF-16-surrogate-pair XML numeric character references any more.

  Workbook workbook = new XSSFWorkbook(file); 
  Sheet sheet = workbook.getSheetAt(0);  
  System.out.println("Success.");
 }
}

 类似资料:
  • 问题内容: 我正在处理一些XML,其中包含以下字符串: 有的,我传递给各节点的字符串将有字符,如,,,等: 由于,此无效。 我无法将这些字符串包装在CDATA中,因为它们必须保持原样。我试图寻找一个字符列表,这些字符如果不包含在CDATA中就不能放入XML节点中。 有人可以指出我的方向或向我提供一系列非法字符吗? 问题答案: 唯一的非法字符,并且(和或在属性)。 他们使用XML实体进行了转义,在这

  • 本文向大家介绍jQ处理xml文件和xml字符串的方法(详解),包括了jQ处理xml文件和xml字符串的方法(详解)的使用技巧和注意事项,需要的朋友参考一下 1.xml文件 2.jQuery代码 3.jQuery处理xml字符串 以上就是小编为大家带来的jQ处理xml文件和xml字符串的方法(详解)全部内容了,希望大家多多支持呐喊教程~

  • 我需要序列化一个包含字符串的文档,如

  • 本文向大家介绍python判断给定的字符串是否是有效日期的方法,包括了python判断给定的字符串是否是有效日期的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python判断给定的字符串是否是有效日期的方法。分享给大家供大家参考。具体分析如下: 这里python判断给定的字符串是否是一个有效的日期,如果是一个日期格式的字符串,该函数返回True,否则返回False 希望本文所述对大

  • 问题内容: 我需要一个正则表达式或PHP中的函数来验证字符串是否是一个很好的XML元素名称。 表格w3schools: XML元素必须遵循以下命名规则: 名称可以包含字母,数字和其他字符 名称不能以数字或标点符号开头 名称不能以字母xml(或XML或Xml等)开头 名称不能包含空格 我可以编写一个基本的正则表达式来检查规则1,2和4,但是它不能解决所有允许的标点符号,也不能解决第三条规则 友善更新

  • 问题内容: 我正在寻找Java代码来检查字符串是否为有效的XML。 问题答案: 用正则表达式验证XML是不可能的。XML不是常规语言。 使用XML解析器尝试将字符串解析为XML,或者对照模式(例如DTD或XSD文件)验证XML文档。