Java SAX API簡(jiǎn)介

2018-02-12 19:09 更新

Java XML教程 - Java SAX API簡(jiǎn)介


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

SAX是一種用于訪問XML文檔的事件驅(qū)動(dòng)的串行訪問機(jī)制。

此機(jī)制經(jīng)常用于傳輸和接收XML文檔。

SAX是一種狀態(tài)獨(dú)立處理,其中元素的處理不依賴于其他元素。StAX是狀態(tài)相關(guān)處理。

SAX是一個(gè)事件驅(qū)動(dòng)模型。 當(dāng)使用SAX解析器時(shí),我們提供了回調(diào)方法,并且解析器在讀取XML數(shù)據(jù)時(shí)調(diào)用它們。

在SAX中,我們不能回到文檔的早期部分,我們只能處理元素逐個(gè)元素,從開始到結(jié)束。


何時(shí)使用SAX

SAX是快速和高效的,并且它對(duì)于狀態(tài)無關(guān)的過濾是有用的。當(dāng)遇到元素標(biāo)記和時(shí),SAX解析器調(diào)用一個(gè)方法當(dāng)發(fā)現(xiàn)文本時(shí)調(diào)用不同的方法。

SAX比DOM要求更少的內(nèi)存,因?yàn)镾AX不像DOM那樣創(chuàng)建XML數(shù)據(jù)的內(nèi)部樹結(jié)構(gòu)。

使用SAX解析XML文件

在下面我們將看到一個(gè)輸出所有SAX事件的演示應(yīng)用程序。它是從包中擴(kuò)展 DefaultHandler org.xml.sax.helpers 如下。

public class Main extends DefaultHandler {

以下代碼設(shè)置了解析器并啟動(dòng)它:

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

這些代碼行創(chuàng)建一個(gè)SAXParserFactory實(shí)例,由 javax.xml.parsers.SAXParserFactory 系統(tǒng)屬性的設(shè)置決定。

工廠被設(shè)置為支持XML命名空間將 setNamespaceAware 設(shè)置為 true 然后通過 newSAXParser()方法從工廠獲取SAXParser實(shí)例。

然后它處理開始文檔和結(jié)束文檔事件:

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

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

之后,它使用 System.out.println 打印消息一旦方法是由解析器調(diào)用。

遇到開始標(biāo)記或結(jié)束標(biāo)記時(shí),根據(jù)需要,將標(biāo)記的名稱作為String傳遞到 startElement endElement 方法。

當(dāng)遇到開始標(biāo)記時(shí),它定義的任何屬性都會(huì)在 Attributes 列表中傳遞。

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

元素中的字符作為字符數(shù)組傳遞,以及字符數(shù)和指向第一個(gè)字符的數(shù)組的偏移量。

  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));
  }

}

上面的代碼生成以下結(jié)果。


錯(cuò)誤處理程序

解析器可以生成三種錯(cuò)誤:

  • 致命錯(cuò)誤
  • 錯(cuò)誤
  • 警告

當(dāng)發(fā)生致命錯(cuò)誤時(shí),解析器無法繼續(xù)。

對(duì)于非致命錯(cuò)誤和警告,默認(rèn)錯(cuò)誤處理程序不會(huì)生成異常,也不會(huì)顯示任何消息。

下面的行安裝我們自己的錯(cuò)誤處理程序。

reader.setErrorHandler(new MyErrorHandler());

MyErrorHandler 類實(shí)現(xiàn)標(biāo)準(zhǔn) 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模式驗(yàn)證

我們可以在使用SAXParser解析期間打開XML模式驗(yàn)證。

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

以下代碼顯示了當(dāng)使用DefaultHandler時(shí)我們不需要實(shí)現(xiàn)所有的方法,我們只需要提供實(shí)現(xiàn)我們關(guān)心的方法。

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中的錯(cuò)誤處理程序方法來處理SAX錯(cuò)誤

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

下面的代碼選擇實(shí)現(xiàn) ContentHandler 接口并提供所有必要方法的實(shí)現(xiàn)。

它還實(shí)現(xiàn) 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");
    }
  }

}
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)