JAVA SAX解析器拆分调用字符()

时间:2010-12-31 02:11:20

标签: java xml

我正在做一个解析XML中的一些数据的项目。

例如,XML是

<abc>abcdefghijklmno</abc>

我需要解析“abcdefghijkmnlp”。

但是当我测试我的解析时,我发现了一个大问题:

public class parser{
    private boolean hasABC = false;


        //Constructor HERE
        ......................
        ......................

     @Override
     public void startDocument () throws SAXException{  
     }

     @Override
     public void endDocument () throws SAXException{  
     }

     @Override
     public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{  
          if ("abc".equalsIgnoreCase(localName)) {
              this.hasABC = true;
          }
      }
      @Override
      public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
            if ("abc".equalsIgnoreCase(localName)) {
                 this.hasABC = false;
            }
       }
       @Override
       public void characters(char ch[], int start, int length){
            String content = new String(ch, start, length).trim(); 
            if(this.hasABC){
                 System.out.println("ABC = " + content);
            }
        }
    }

我发现解析器已经解析了两次标记 系统打印输出是,

ABC = abcdefghi

ABC = jklmno&lt;&lt; ============拆分邮件

为什么解析器会自动回调两次字符()????

XML是否有一些“\ n”或“\ r”???

4 个答案:

答案 0 :(得分:35)

Parser多次调用characters方法,因为它可以并且允许每个规范。这有助于快速解析并保持较低的内存占用。如果您想要一个字符串,请在StringBuilder中创建一个新的startElement对象,并在endElement方法上对其进行处理。

答案 1 :(得分:8)

您会感到惊讶,但这是一个记录在案的行为,即您不能假设解析器将读取并返回单个回调中元素的所有文本数据。我之前有过相同的经历。您需要编码来处理这种情况,或者您可以切换到Stax parser。您可以使用CharArrayWriter在多个回调中累积数据。

请参阅下面的JavaDoc of ContentHandler.characters(...)

  

Parser会调用此方法   报告每个字符数据块。   SAX解析器可能会返回所有连续的   单个块中的字符数据,或   他们可能将它分成几个块;   但是,任何人物中的所有人物   单一事件必须来自同一事件   外部实体使定位器   提供有用的信息。

答案 2 :(得分:5)

您可以更改开始,结束和字符方法,如:

  • 添加“全局”内容变量
  • 然后在start方法(content == null)
  • 中将其null
  • 在end方法中你可以println或将该内容字符串添加到某个对象
  • 在字符方法中你可以制作if / else:

    if (content == null)
    {
        content = new String(ch, start, length);
    } else {
        content += new String(ch, start, length);
    }
    

    野蛮的方式(最好用stringbuilder完成)但是工作和“字符串”不再分裂。

答案 3 :(得分:3)

这是SAX的一项功能。解析器可以拆分文本段并根据需要多次调用characters方法。

其原因在于性能,SAX优先于易用性。 SAX可能已经用完了它的内部缓冲区,所以为了避免复制它,它会将它到目前为止的数据传递给你的代码。