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

在Java中使用SAX解析检测“内联字符串”单元格值时出现问题

韦安顺
2023-03-14

我有一个巨大的excel文件,我正试图用JAVA中的SAX解析器解析它。我主要使用ApachePOI库并与之合作。XLSX文件。以下是压缩excel文件夹中xml内容的外观,位于/xl/worksheets/sheet1。xml我正在尝试阅读:

<row r="1">
<c r="A1" t="inlineStr"><is><t>my value 1</t></is></c>
<c r="B1" t="inlineStr"><is><t>my value 2</t></is></c>
<c r="C1" t="inlineStr"><is><t>my value 3</t></is></c>
</row>

这个特殊的excel文件正在使用内联字符串值,如上所示。

此my函数执行程序以读取文件:

public void executeExcelDataExtraction() throws IOException, OpenXML4JException, SAXException, ParserConfigurationException, XMLStreamException, FactoryConfigurationError {
    OPCPackage pkg = OPCPackage.open(XLSX_INPUT_FILE.xlsx);
    XSSFReader r = new XSSFReader( pkg );
    SharedStringsTable sst = r.getSharedStringsTable();
    ImportArticleDataProcessorExcelFileReaderFactory handlerFactory = new 
         ImportArticleDataProcessorExcelFileReaderFactory(sst);
    XMLReader parser = fetchSheetParser(handlerFactory);
    Iterator<InputStream> sheets = r.getSheetsData();
    if (sheets instanceof XSSFReader.SheetIterator) {
        XSSFReader.SheetIterator sheetiterator = 
             (XSSFReader.SheetIterator)sheets;
        while(sheetiterator.hasNext()) {
            System.out.println("Processing new sheet:\n");
            InputStream sheet = sheets.next();
            InputSource sheetSource = new InputSource(sheet);
            parser.parse(sheetSource);
            rowCache = handlerFactory.getRowCache();
            sheet.close();
            pkg.close();
            if(!rowCache.isEmpty()) 
                createCategoryMap(rowCache);                
        }
    }
}

这是我的sheet handler工厂类,用于上面的函数。

import java.util.LinkedList;
import java.util.List;

import org.xml.sax.Attributes;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ImportArticleDataProcessorExcelFileReaderFactory extends DefaultHandler{

    private static final String ROW_EVENT = "row";
    private static final String CELL_EVENT = "c";
    private SharedStringsTable sst;
    private String lastContents;
    private boolean nextIsString;
    private List<String> cellCache = new LinkedList<>();
    private List<String[]> rowCache = new LinkedList<>();

    ImportArticleDataProcessorExcelFileReaderFactory(SharedStringsTable sst) {
        this.sst = sst;
    }

    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
        // c => cell
        if (CELL_EVENT.equals(name)) {
            String cellType = attributes.getValue("t");
            if(cellType != null && cellType.equals("s")) {
                nextIsString = true;
            } else {
                nextIsString = false;
            }
        } else if (ROW_EVENT.equals(name)) {
            if (!cellCache.isEmpty()) {
                rowCache.add(cellCache.toArray(new String[cellCache.size()]));
            }
            cellCache.clear();
        }
        lastContents = "";
    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {
        // Process the last contents as required.
        // Do now, as characters() may be called more than once
        if(nextIsString) {
            int idx = Integer.parseInt(lastContents);
            lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            nextIsString = false;
        }

        // v => contents of a cell
        // Output after we've seen the string contents
        if(name.equals("v")) {
            cellCache.add(lastContents.trim());
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        lastContents += new String(ch, start, length);
    }

    public List<String[]> getRowCache() {
        return rowCache;
    }

}

所有其他没有内联字符串的excel文件都能够成功读取,但是对于内部有内联字符串的文件,算法只读取cell Type=inlineStr,但永远不会获得正确的值。

我想要的:

我只想打印内联字符串单元格中的值,例如,在我的示例中,它是“我的值1”、“我的值2”和“我的值3”

共有1个答案

暨弘懿
2023-03-14

如果有人正在寻找类似的解决方案,只是想让你知道,我已经解决了这几行,在我的类中添加这几行:

public void startElement(String uri, String localName, String name){

        // rest of the code...

        inlineStr = false;
        if(cellType != null && cellType.equals("inlineStr")) {
            inlineStr = true;
        } 
        ...
}

public void endElement(String uri, String localName, String name){

        // rest of the code...

       if(name.equals("t") && inlineStr) {
          cellCache.add(lastContents.trim());
       }
       ...
}

上述工厂类中的void characters函数正确识别单元格的内容,并且我的答案中给出的更改成功地用内联字符串单元格中的所有值填充cellCache列表。

请参考上面评论中@Axel的答案,并遵循此答案查找您的来源:如何在java中使用apache事件模型解析excel文件时检查包含日期和指数的字符串中的数字

 类似资料:
  • 我有一个代表学生实体的字符串: 学生实体类是: 对于解析字符串,我使用以下代码: 响应1是一个httpresponse的主体,它代表我来自描述的字符串。 例外情况:

  • 问题内容: 我有一个XML文件,我需要在其中搜索特定的标签并更新其值。问题在于,使用Sax解析器是“必须的”。我必须通过“仅”使用Sax解析器来找到这些标签,dom stax j4dom dom4j解析器不在考虑范围之内。 我可以通过将xml文件转换为字符串并使用sax解析器对其进行解析并按对象附加新值来完成此任务吗?可以吗 或您会推荐什么? 问题答案: 这是一个有效的代码,只需添加缺少的导入。它

  • 我怀疑这可能是VBA的工作,这超出了我的能力。但情况是这样的: 表1(CAS1)中的A列包含x行文本值 第2页(CAS2)中的A列包含x行文本值 A部分-对于CAS1中的每个行值,我需要知道字符串是否包含在CAS2中的任何单元格中。不完全匹配,字符串只能是搜索单元格的一部分。 B部分-我需要知道CAS2中包含CAS1值的每个单元格的单元格值(如果它们确实存在,可以在CAS1中搜索的单元格旁边的单元

  • 问题内容: 我有这样的XML字符串 我遵循此帮助 用Java查询XML的最简单方法 我的代码: 我想获取味精节点值,但出现异常 我不会为这个简单的任务使用一些外部库。请指导我如何获取其他节点的值。谢谢 问题答案: 您不能将其重复用于多个调用,因为它会自动关闭。因此,您将获得IO异常。试试这个 编辑: 更好的方法是使用A解析您的XML并构建第一个(使用JAXP的DOM API),然后可以在多个XPa

  • 问题内容: 我正在尝试分析堆栈溢出数据转储,其中一个表称为posts.xml,其中有大约1000万个条目。样本XML: 我想解析此xml,但仅加载xml的某些属性,例如ID,PostTypeId,AcceptedAnswerId和其他2个属性。SAX中是否有办法只加载这些属性?如果有的话怎么办?对于SAX来说我还很陌生,所以一些指导会有所帮助。 否则,加载整个程序只会很慢,而且某些属性也不会被使用

  • 问题内容: 在Java中,有一种检查条件的方法: “此单个字符是否完全出现在字符串x中” 不使用循环? 问题答案: 你可以使用。 如果中存在,则返回。如果不是,则返回-1。因此,非负返回值表示。