1

我正在尝试使用 Sax 来解析非常大的 XML 文件。100 的兆。问题是解析器一次准确地读取 2048 个字符并终止。我使用回调“public void characters(...)”将标签的值分成两部分。例如,第一部分在位置 2044 的字符数组中,长度为 4“2013”​​,第二部分在位置 0 的字符数组“-09-30”,长度为 6。它应该是日期值“2013-09-30”如果收到一部分。我能避免这种分裂吗?任何人都可以帮助我吗?

    public void characters(char[] ch, int start, int length) throws SAXException {
    if (Main.errorProceso==0){
    for(int i=0;i < strlista.size();i++){
    if(strlista.get(i).equals(sEtiqueta_actual)){
    if (sEtiqueta_actual.equals("Root.Header.Body.")){
    String FileNm= String.valueOf(ch, start, length);
    if (!FileNm.substring(0,2).equalsIgnoreCase("XX")){
    logger.info("El identificador no es XX");
    Main.errorProceso=1;
    i=strlista.size()+1;
    sEtiqueta_actual="";
    }
    else{
    sCod_Fichero=FileNm.substring(0,2)+XXteFormat.format(XXte);
    }
    }
    else if (sEtiqueta_actual.equals("Root.Header.Date.")){
    String aux = String.valueOf(ch, start, length).split("T")[0];
    try {
    sFec=newFormat.format(oldFormat.parse(aux));
    } catch (ParseException e) {
    logger.error(e.getLocalizedMessage());
    Main.errorProceso=1;
    }
    }
    else if (sEtiqueta_actual.equals("Root.Header2.Body2.")){
    sNum_Total=String.valueOf(ch, start, length);
    }
    else if (sEtiqueta_actual.equals("Root.Header3.Body3.Spcf.Inst.")){
    sImp =String.valueOf(ch, start, length);
    }
    .
    .
    .
    else if (sEtiqueta_actual.equals("Root.Header3.Body3.Spcf.Req.")){
    try {
    sFec2=newFormat.format(oldFormat.parse(String.valueOf(ch, start, length)));
    } catch (ParseException e) {
    logger.error(e.getLocalizedMessage());
    Main.errorProceso=1;
    }
    }
    }
    }
4

2 回答 2

6

这正是 SAX 解析器的工作方式。如果您可以增加缓冲区大小(我不知道该怎么做),那将无济于事;它只会减少您将值分解为碎片的次数。

SAX 解析器可以在任何需要的地方自由拆分字符串(文档)。它这样做是为了提高效率;避免使用内存;为简化实施;或图书馆开发人员提出的任何其他原因。

因此,如果您想将您的琴弦连成一体,您需要自己动手。一个简单的解决方案,假设您永远不需要使用子元素累积字符串值:

  • 添加一个StringBuffer accumulator到你的实现类,以及一个 isAccumulating 标志。
  • startElement中,如果元素是感兴趣的,则设置isAccumulating标志。
  • characters中,如果isAccumulating设置了标志,则将字符附加到累加器。
  • endElement中,如果isAccumulating设置了标志,则对累积的字符串执行任何您需要执行的操作,然后清除标志并清空缓冲区。

如果您可能需要收集带有子元素的值,您可以isAccumulating从标志更改为整数深度计数器。startElement如果计数器大于 0,则递增计数器,如果元素需要收集其值,则将其设置为 1。characters如果计数器大于 0,则追加字符。如果计数器endElement大于零,则递减计数器,如果结果为 0,则处理并清除累加器。

于 2013-09-30T15:39:18.487 回答
0

在进一步进入该功能之前使用String.trim()并检查String.length()>=0characters()

并使用 astack来跟踪cData属于哪个标签。然后你就可以append了。

于 2014-01-29T05:40:26.693 回答