Java SAX API简介

2018-02-12 19:09 更新

Java XML教程 - Java SAX API简介


Java SAX XML解析器代表Simple API for XML(SAX)解析器。

SAX是一种用于访问XML文档的事件驱动的串行访问机制。

此机制经常用于传输和接收XML文档。

SAX是一种状态独立处理,其中元素的处理不依赖于其他元素。StAX是状态相关处理。

SAX是一个事件驱动模型。 当使用SAX解析器时,我们提供了回调方法,并且解析器在读取XML数据时调用它们。

在SAX中,我们不能回到文档的早期部分,我们只能处理元素逐个元素,从开始到结束。


何时使用SAX

SAX是快速和高效的,并且它对于状态无关的过滤是有用的。当遇到元素标记和时,SAX解析器调用一个方法当发现文本时调用不同的方法。

SAX比DOM要求更少的内存,因为SAX不像DOM那样创建XML数据的内部树结构。

使用SAX解析XML文件

在下面我们将看到一个输出所有SAX事件的演示应用程序。它是从包中扩展 DefaultHandler org.xml.sax.helpers 如下。

public class Main extends DefaultHandler {

以下代码设置了解析器并启动它:

    SAXParserFactory spf = SAXParserFactory.newInstance();
    spf.setNamespaceAware(true);
    spf.setValidating(true);
    parser = spf.newSAXParser();
    parser.parse(file, this);

这些代码行创建一个SAXParserFactory实例,由 javax.xml.parsers.SAXParserFactory 系统属性的设置决定。

工厂被设置为支持XML命名空间将 setNamespaceAware 设置为 true 然后通过 newSAXParser()方法从工厂获取SAXParser实例。

然后它处理开始文档和结束文档事件:

  public void startDocument() {
    System.out.println("Start document: ");
  }

  public void endDocument() {
    System.out.println("End document: ");
  }

之后,它使用 System.out.println 打印消息一旦方法是由解析器调用。

遇到开始标记或结束标记时,根据需要,将标记的名称作为String传递到 startElement endElement 方法。

当遇到开始标记时,它定义的任何属性都会在 Attributes 列表中传递。

  public void startElement(String uri, String localName, String qname, Attributes attr) {
    System.out.println("Start element: local name: " + localName + " qname: " + qname + " uri: "
        + uri);
  }

元素中的字符作为字符数组传递,以及字符数和指向第一个字符的数组的偏移量。

  public void characters(char[] ch, int start, int length) {
    System.out.println("Characters: " + new String(ch, start, length));
  }

完整的代码。

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class Main extends DefaultHandler {

  private static Main handler = null;

  private SAXParser parser = null;
  public static void main(String args[]) {
    if (args.length == 0) {
      System.out.println("No file to process. Usage is:" + "\njava TrySAX <filename>");
      return;
    }
    File xmlFile = new File(args[0]);
    handler = new Main();
    handler.process(xmlFile);
  }

  private void process(File file) {
    SAXParserFactory spf = SAXParserFactory.newInstance();
    spf.setNamespaceAware(true);
    spf.setValidating(true);
    System.out.println("Parser will " + (spf.isNamespaceAware() ? "" : "not ")
        + "be namespace aware");
    System.out.println("Parser will " + (spf.isValidating() ? "" : "not ") + "validate XML");
    try {
      parser = spf.newSAXParser();
      System.out.println("Parser object is: " + parser);
    } catch (SAXException e) {
      e.printStackTrace(System.err);
      System.exit(1);
    } catch (ParserConfigurationException e) {
      e.printStackTrace(System.err);
      System.exit(1);
    }
    System.out.println("\nStarting parsing of " + file + "\n");
    try {
      parser.parse(file, this);
    } catch (IOException e) {
      e.printStackTrace(System.err);
    } catch (SAXException e) {
      e.printStackTrace(System.err);
    }
  }

  public void startDocument() {
    System.out.println("Start document: ");
  }

  public void endDocument() {
    System.out.println("End document: ");
  }

  public void startElement(String uri, String localName, String qname, Attributes attr) {
    System.out.println("Start element: local name: " + localName + " qname: " + qname + " uri: "
        + uri);
  }

  public void endElement(String uri, String localName, String qname) {
    System.out.println("End element: local name: " + localName + " qname: " + qname + " uri: "
        + uri);
  }

  public void characters(char[] ch, int start, int length) {
    System.out.println("Characters: " + new String(ch, start, length));
  }

  public void ignorableWhitespace(char[] ch, int start, int length) {
    System.out.println("Ignorable whitespace: " + new String(ch, start, length));
  }

}

上面的代码生成以下结果。


错误处理程序

解析器可以生成三种错误:

  • 致命错误
  • 错误
  • 警告

当发生致命错误时,解析器无法继续。

对于非致命错误和警告,默认错误处理程序不会生成异常,也不会显示任何消息。

下面的行安装我们自己的错误处理程序。

reader.setErrorHandler(new MyErrorHandler());

MyErrorHandler 类实现标准 org.xml.sax.ErrorHandler 接口,并定义一种方法来获取任何SAXParseException提供的异常信息。

完整的代码。

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

class MyErrorHandler implements ErrorHandler {
  public void warning(SAXParseException e) throws SAXException {
    show("Warning", e);
    throw (e);
  }

  public void error(SAXParseException e) throws SAXException {
    show("Error", e);
    throw (e);
  }

  public void fatalError(SAXParseException e) throws SAXException {
    show("Fatal Error", e);
    throw (e);
  }

  private void show(String type, SAXParseException e) {
    System.out.println(type + ": " + e.getMessage());
    System.out.println("Line " + e.getLineNumber() + " Column " + e.getColumnNumber());
    System.out.println("System ID: " + e.getSystemId());
  }
}

// Installation and Use of an Error Handler in a SAX Parser

public class SAXCheck {
  static public void main(String[] arg) throws Exception {
    boolean validate = false;
    validate = true;

    SAXParserFactory spf = SAXParserFactory.newInstance();
    spf.setValidating(validate);

    XMLReader reader = null;
    SAXParser parser = spf.newSAXParser();
    reader = parser.getXMLReader();

    reader.setErrorHandler(new MyErrorHandler());
    InputSource is = new InputSource("test.xml");
    reader.parse(is);
  }
}

XML模式验证

我们可以在使用SAXParser解析期间打开XML模式验证。

import java.io.File;

import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

public class Main {
  public static void main(String args[]) throws Exception {
    String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
    SchemaFactory factory = SchemaFactory.newInstance(language);
    Schema schema = factory.newSchema(new File("yourSchema"));

    SAXParserFactory spf = SAXParserFactory.newInstance();
    spf.setSchema(schema);

    SAXParser parser = spf.newSAXParser();

    // parser.parse(...);
  }
}

DefaultHandler

以下代码显示了当使用DefaultHandler时我们不需要实现所有的方法,我们只需要提供实现我们关心的方法。

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class Main {
  public static void main(String args[]) throws Exception {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser saxParser = factory.newSAXParser();
    DefaultHandler handler = new DefaultHandler() {
      public void startElement(String uri, String localName, String qName,
          Attributes attributes) throws SAXException {
        System.out.println(qName);
      }

      public void characters(char ch[], int start, int length)
          throws SAXException {
        System.out.println(new String(ch, start, length));
      }
    };

    saxParser.parse(args[0], handler);
  }
}

以下代码通过覆盖DefaultHandler中的错误处理程序方法来处理SAX错误

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class Main {
  public static void main(String[] argv) throws Exception {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setValidating(true);
    SAXParser parser = factory.newSAXParser();
    SaxHandler handler = new SaxHandler();
    parser.parse("sample.xml", handler);
  }
}

class SaxHandler extends DefaultHandler {
  public void startElement(String uri, String localName, String qName, Attributes attrs)
      throws SAXException {
    if (qName.equals("order")) {
    }
  }
  public void error(SAXParseException ex) throws SAXException {
    System.out.println("ERROR: [at " + ex.getLineNumber() + "] " + ex);
  }
  public void fatalError(SAXParseException ex) throws SAXException {
    System.out.println("FATAL_ERROR: [at " + ex.getLineNumber() + "] " + ex);
  }
  public void warning(SAXParseException ex) throws SAXException {
    System.out.println("WARNING: [at " + ex.getLineNumber() + "] " + ex);
  }
}

ContentHandler

下面的代码选择实现 ContentHandler 接口并提供所有必要方法的实现。

它还实现 ErrorHandler 接口。

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

public class Main {
  static public void main(String[] arg) throws Exception {
    String filename = "yourXML.xml";
    // Create a new factory that will create the parser.
    SAXParserFactory spf = SAXParserFactory.newInstance();

    // Create the XMLReader to be used to parse the document.
    SAXParser parser = spf.newSAXParser();
    XMLReader reader = parser.getXMLReader();

    // Specify the error handler and the content handler.
    reader.setErrorHandler(new MyErrorHandler());
    reader.setContentHandler(new MyContentHandler());
    // Use the XMLReader to parse the entire file.
    InputSource is = new InputSource(filename);
    reader.parse(is);
  }
}

class MyContentHandler implements ContentHandler {
  private Locator locator;

  /**
   * The name and of the SAX document and the current location within the
   * document.
   */
  public void setDocumentLocator(Locator locator) {
    this.locator = locator;
    System.out.println("-" + locator.getLineNumber() + "---Document ID: "
        + locator.getSystemId());
  }

  /** The parsing of a document has started.. */

  public void startDocument() {
    System.out.println("-" + locator.getLineNumber()
        + "---Document parse started");
  }

  /** The parsing of a document has completed.. */
  public void endDocument() {
    System.out.println("-" + locator.getLineNumber()
        + "---Document parse ended");
  }

  /** The start of a namespace scope */
  public void startPrefixMapping(String prefix, String uri) {
    System.out.println("-" + locator.getLineNumber()
        + "---Namespace scope begins");
    System.out.println("     " + prefix + "=\"" + uri + "\"");
  }

  /** The end of a namespace scope */
  public void endPrefixMapping(String prefix) {
    System.out.println("-" + locator.getLineNumber()
        + "---Namespace scope ends");
    System.out.println("     " + prefix);
  }

  /** The opening tag of an element. */
  public void startElement(String namespaceURI, String localName, String qName,
      Attributes atts) {
    System.out.println("-" + locator.getLineNumber()
        + "---Opening tag of an element");
    System.out.println("       Namespace: " + namespaceURI);
    System.out.println("      Local name: " + localName);
    System.out.println("  Qualified name: " + qName);
    for (int i = 0; i < atts.getLength(); i++) {
      System.out.println("       Attribute: " + atts.getQName(i) + "=\""
          + atts.getValue(i) + "\"");
    }
  }

  /** The closing tag of an element. */
  public void endElement(String namespaceURI, String localName, String qName) {
    System.out.println("-" + locator.getLineNumber()
        + "---Closing tag of an element");
    System.out.println("       Namespace: " + namespaceURI);
    System.out.println("      Local name: " + localName);
    System.out.println("  Qualified name: " + qName);
  }

  /** Character data. */
  public void characters(char[] ch, int start, int length) {
    System.out.println("-" + locator.getLineNumber() + "---Character data");
    showCharacters(ch, start, length);
  }

  /** Ignorable whitespace character data. */
  public void ignorableWhitespace(char[] ch, int start, int length) {
    System.out.println("-" + locator.getLineNumber() + "---Whitespace");
    showCharacters(ch, start, length);
  }

  /** Processing Instruction */
  public void processingInstruction(String target, String data) {
    System.out.println("-" + locator.getLineNumber()
        + "---Processing Instruction");
    System.out.println("         Target: " + target);
    System.out.println("           Data: " + data);
  }

  /** A skipped entity. */
  public void skippedEntity(String name) {
    System.out.println("-" + locator.getLineNumber() + "---Skipped Entity");
    System.out.println("           Name: " + name);
  }

  /**
   * Internal method to format arrays of characters so the special whitespace
   * characters will show.
   */
  public void showCharacters(char[] ch, int start, int length) {
    System.out.print("        \"");
    for (int i = start; i < start + length; i++)
      switch (ch[i]) {
      case "\n":
        System.out.print("\\n");
        break;
      case "\r":
        System.out.print("\\r");
        break;
      case "\t":
        System.out.print("\\t");
        break;
      default:
        System.out.print(ch[i]);
        break;
      }
    System.out.println("\"");
  }
}

class MyErrorHandler implements ErrorHandler {
  public void warning(SAXParseException e) throws SAXException {
    show("Warning", e);
    throw (e);
  }

  public void error(SAXParseException e) throws SAXException {
    show("Error", e);
    throw (e);
  }

  public void fatalError(SAXParseException e) throws SAXException {
    show("Fatal Error", e);
    throw (e);
  }

  private void show(String type, SAXParseException e) {
    System.out.println(type + ": " + e.getMessage());
    System.out.println("Line " + e.getLineNumber() + " Column "
        + e.getColumnNumber());
    System.out.println("System ID: " + e.getSystemId());
  }
}

定位器

以下代码显示了如何从DefaultHandler访问Locator接口。

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class Main{
  public static void main(String[] args) throws Exception {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setValidating(true);
    SAXParser parser = factory.newSAXParser();
    parser.parse("sample.xml", new SampleOfXmlLocator());
  }
}
class SampleOfXmlLocator extends DefaultHandler {
  private Locator locator;
  public void setDocumentLocator(Locator locator) {
    this.locator = locator;
  }
  public void startElement(String uri, String localName, String qName, Attributes attrs)
      throws SAXException {
    if (qName.equals("order")) {
      System.out.println("here process element start");
    } else {
      String location = "";
      if (locator != null) {
        location = locator.getSystemId(); // XML-document name;
        location += " line " + locator.getLineNumber();
        location += ", column " + locator.getColumnNumber();
        location += ": ";
      }
      throw new SAXException(location + "Illegal element");
    }
  }

}
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号