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

reb*_*cca 21 java xml

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

例如,XML是

<abc>abcdefghijklmno</abc>
Run Code Online (Sandbox Code Playgroud)

我需要解析"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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

ABC = abcdefghi

ABC = jklmno << ============拆分消息

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

XML是否有一些"\n"或"\ r"?

Cha*_*tni 35

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


Ara*_*ram 8

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

请参阅下面的ContentDandler.characters的JavaDoc(...)

解析器将调用此方法来报告每个字符数据块.SAX解析器可以在一个块中返回所有连续的字符数据,或者它们可以将它分成几个块; 但是,任何单个事件中的所有字符都必须来自同一个外部实体,以便Locator提供有用的信息.


小智 5

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

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

    if (content == null)
    {
        content = new String(ch, start, length);
    } else {
        content += new String(ch, start, length);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    野蛮的方式(最好用stringbuilder做)但工作和"字符串"不再分裂.