第一百八十四节 Java XML教程 - Java XML API、Java SAX API

Java XML教程 - Java XML API

SAX API

下面是关键的SAX API的摘要:

用法
SAXParserFactory创建由系统属性javax.xml.parsers.SAXParserFactory确定的解析器的实例。
SAXParserSAXParser接口定义了几个重载的parse()方法。
SAXReaderSAXParser包装一个SAXReader,并从SAXParser的getXMLReader()方法返回。
DefaultHandlerDefaultHandler实现了ContentHandler,ErrorHandler,DTDHandler,和EntityResolver接口。 通过使用DefaultHandler,我们可以只覆盖我们需要的那些。
ContentHandler此接口定义回调方法,如startDocument,endDocument,startElement和endElement。 这些方法在识别XML标记时调用。它还定义了被调用的方法characters()当解析器遇到XML元素中的文本时。它定义被调用的processingInstruction()当解析器遇到内联处理指令时。
ErrorHandler它使用error(),fatalError()和warning()方法来响应各种解析错误。 默认的错误处理程序只会抛出致命错误和的异常忽略验证错误。
DTDHandler用于处理DTD
EntityResolver它的resolveEntity()方法用于标识数据。

我们通常实现大多数 ContentHandler 方法。

为了提供更稳健的实现,我们可以从ErrorHandler实现方法。

SAX包

SAX解析器在下表中列出的软件包中定义。

描述
org.xml.sax定义SAX接口。
org.xml.sax.ext定义用于更高级SAX处理的SAX扩展。
org.xml.sax.helpers定义SAX API的辅助类。
javax.xml.parsers定义SAXParserFactory类,它返回SAXParser。

DOM API

javax.xml.parsers.DocumentBuilderFactory 类返回一个 DocumentBuilder 实例。

我们使用 DocumentBuilder 实例来产生一个 Document 对象退出XML文档。

构建器由系统属性 javax.xml.parsers.DocumentBuilderFactory 确定。

DocumentBuilder 中的 newDocument()方法可以创建一个实现 org.w3c.dom.Document 接口的空Document。

我们可以使用其中一个构建器的解析方法来创建一个 Document 从现有的XML文档。

DOM包

文档对象模型实现在中定义下表中列出的软件包。

描述
org.w3c.dom定义XML文档的DOM编程接口。
javax.xml.parsers定义DocumentBuilderFactory类和DocumentBuilder类。

XSLT API

TransformerFactory 创建一个 Transformer 对象。

XSLT API在下表中显示的包中定义。

描述
javax.xml.transform定义TransformerFactory和Transformer类。 我们可以从变换器对象调用transform()方法来进行变换。
javax.xml.transform.dom用于从DOM创建输入和输出对象的类。
javax.xml.transform.sax用于从SAX解析器创建输入对象和从SAX事件处理程序输出对象的类。
javax.xml.transform.stream用于从I / O流创建输入对象和输出对象的类。

StAX APIs

StAX为开发人员提供了SAX和DOM解析器的替代方法。

StAX可以用更少的内存进行高性能流过滤,处理和修改。

StAX是用于流式XML处理的标准的双向拉解析器接口。

StAX提供比SAX更简单的编程模型,并且比DOM更高的内存效率。

StAX可以解析和修改XML流作为事件。

StAX包

StAX APIs在下表中显示的包中定义。

描述
javax.xml.stream定义迭代XML文档元素的XMLStreamReader接口。 定义XMLStreamWriter接口,指定如何写入XML。
javax.xml.transform.stax提供StAX特定的转换API。

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

}

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值