sax使用教程
使用SAX API时,所有输入均以org.xml.sax.InputSource
类开头。 此类包含在SAX API中,并提供输入的规范(通过文件或I / O流之类的标准Java构造),以及公共和系统ID。 然后,SAX在解析时从InputSource
提取此信息,并且能够解析外部实体和其他文档源特定的资源。
同样,当您在SAX周围使用包装器时(例如JAXP API),您可以调用不同的方法。 最终,解析使用SAX InputSource
。 例如,考虑清单1中所示的代码片段,该片段使用JAXP发起SAX解析。
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.parse(myFile, myHandler);
即使传入了java.io.File
,也要先将其转换为SAX InputSource
然后InputSource
递给基础SAX实现。 发生这种转换的原因是,此JAXP代码最终访问了org.xml.sax.XMLReader
类,该类仅提供清单2中所示的两个签名来启动解析。
public void parse(InputSource inputSource);
public void parse(String systemID);
除了这些基础知识之外,大多数SAX解析器实现(例如Apache Xerces)实际上将字符串系统ID转换为InputSource
并将其委托给接受InputSource
的parse()
版本。 无论您如何编写应用程序代码,SAX最终都会收到一个InputSource
进行解析。 但是,并非所有最终的方法都同样好。
为了避免代码带来令人不快的惊喜,最好直接使用SAX InputSource
类,而不是让JAXP或SAX实现为您完成此任务。 因为实现必须处理所有可能的情况,所以您经常会发现清单3所示的代码构造InputSource
实例。
InputSource inputSource = new InputSource();
// May be a null parameter
inputSource.setByteStream(inputStream);
// May be a null parameter
inputSource.setCharacterStream(reader);
// May be a null parameter
inputSource.setSystemId(systemId);
// May be a null parameter
inputSource.setPublicId(publicId);
// Derived parameter
inputSource.setEncoding(encoding);
从注释中可以看到,许多方法都传递了null
参数。 尽管这些方法可能不需要花费很多时间来执行,但XML解析应用程序中的每一秒都很关键。 不幸的是,这些无操作方法浪费了宝贵的时间。 通过自己构造一个InputSource
实例,您可以将此过程简化为一个或两个方法调用,如清单4所示。
InputSource inputSource = new InputSource(myInputStream);
inputSource.setSystemId("http://www.oreilly.com");
inputSource.setEncoding("UTF-8");
我还使用了setEncoding()
方法来告诉SAX解析器要使用哪种编码。 这在关注国际化或使用多字节字符集的XML应用程序中至关重要。
但是,这里还会出现另一个问题:经常看到手动将编码设置为与提供的输入流所使用的字符编码不同的字符编码(通过java.io.InputStream
或java.io.Reader
)。 如果这些编码不匹配,则可能会发生各种解析问题。 为了避免这种情况,请始终使用Java InputStream
而不是Reader
或String
系统ID(对于JAXP API都是可能的选项)创建InputSource
。 提供InputStream
,SAX实现将流包装在InputStreamReader
。 然后SAX自动从流中检测正确的字符编码。 然后,您可以省略setEncoding()
步骤,从而再次减少方法调用。 结果是一个更快的应用程序,并且始终具有正确的字符编码。
翻译自: https://www.ibm.com/developerworks/xml/library/x-tipsaxis/index.html
sax使用教程