sax数据离散化
注意:本技巧使用JAXP。 这些类也是Java 2 SDK 1.4的一部分,因此,如果安装了此版本,则不需要任何其他软件。 它简要介绍了SAX的基础知识,但是您应该已经了解Java和XML的基础知识。
本技巧介绍了一个应用程序,该应用程序确定哪些雇员要通知特定的紧急情况,然后采取相应的行动。 (实际的联系方式留给读者练习。) 清单1中的源文档仅列出了员工,其部门和他们的状态:
清单1.源文档
<?xml version="1.0"?>
<personnel>
<employee empid="332" deptid="24" shift="night"
status="contact">
JennyBerman
</employee>
<employee empid="994" deptid="24" shift="day"
status="donotcontact">
AndrewFule
</employee>
<employee empid="948" deptid="3" shift="night"
status="contact">
AnnaBangle
</employee>
<employee empid="1032" deptid="3" shift="day"
status="contact">
DavidBaines
</employee>
</personnel>
基本应用
SAX应用程序包括两个部分。 主应用程序创建一个XMLReader
,该XMLReader
实际上解析该文档,并将诸如startElement
和endDocument
事件发送到内容处理程序。 您可以将错误发送到单独的错误处理程序对象。 处理程序对象接收这些事件并对其进行操作。
主应用程序还可以充当内容或错误处理程序(或两者),但是在清单2中,它们是三个单独的类:
清单2.主要应用程序
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
import java.io.IOException;
public class MainSaxApp {
public staticvoid main (String[] args){
try {
StringparserClass = "org.apache.crimson.parser.XMLReaderImpl";
XMLReader reader = XMLReaderFactory.createXMLReader(parserClass);
reader.setContentHandler(new DataProcessor());
reader.setErrorHandler(new ErrorProcessor());
InputSource file = new InputSource("employees.xml");
reader.parse(file);
} catch (IOException ioe) {
System.out.println("IO Exception: "+ioe.getMessage());
} catch(SAXException se) {
System.out.println("SAX Exception: "+se.getMessage());
}
}
}
通过将阅读器的内容处理程序设置为DataProcessor
对象,应用程序将通知阅读器将其事件发送到该对象。 在清单3中 , DataProcessor
很简单,仅在确定是否联系他们之前检查元素的名称和员工的状态:
清单3.内容处理程序
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
public class DataProcessor extends DefaultHandler
{
public voidstartElement (String namespaceUri, String localName,
String qualifiedName, Attributesattributes) {
if(localName.equals("employee")){
if(attributes.getValue("status").equals("contact")){
System.out.println("Contacting employee "+
attributes.getValue("empid"));
//Implement actual contact here
}
}
}
}
ErrorProcessor
类很简单,并且包含在此技巧的源代码中。 (请参阅相关主题下载源代码。)
运行该应用程序时,输出将包括状态属性为contact的所有雇员,无论他们在哪个部门工作:
Contacting employee 332
Contacting employee 948
Contacting employee 1032
过滤数据
到目前为止,该应用程序可以联系所有被列为on duty
雇员,而不论其部门是什么,它都可以很好地工作(或至少希望如此!)。 当您收到仅与特定部门的员工联系的新要求时,您有两种选择:
- 更改内容处理程序并冒各种新错误的风险
- 更改内容处理程序附带的数据,以便仅将适当的员工视为值班人员。
由于其他要求也可能会在以后添加,因此分开实现它们更有意义。
SAX筛选器位于解析器和内容处理程序之间。 它从解析器接收事件,并且除非另有指示,否则将它们原样传递给内容处理程序。 例如,考虑清单4中的此过滤器:
清单4.一个简单的XML过滤器
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
public class DataFilter extends XMLFilterImpl
{
}
XMLFilterImpl
类包含一些方法,这些方法仅将数据传递不变。 将过滤器插入到主应用程序中的流中就足够了(请参见清单5 ):
清单5.将过滤器插入主应用程序
...
XMLReader reader = XMLReaderFactory.createXMLReader(parserClass);
DataFilter filter = new DataFilter();
filter.setParent(reader);
filter.setContentHandler(new DataProcessor());
filter.setErrorHandler(new ErrorProcessor());
filter.parse("employees.xml");
} catch (IOException ioe) {
...
该应用程序照常创建XMLReader
,但实际上是过滤器启动了文件解析,该文件从其父XMLReader
接收事件。 (请记住,过滤器调用super(parent)
。)它将事件传递到其内容处理程序-与原始版本中使用的DataProcessor
对象相同。
到目前为止,过滤器只是将事件传递为不变,因此运行应用程序仍然会产生以下结果:
Contacting employee 332
Contacting employee 948
Contacting employee 1032
但是,安装好过滤器后,您可以轻松进行更改,而无需触碰主应用程序。 例如,在清单6 ,过滤器可以简单地通过其他人的状态设置为消除不在24部门所有员工donotcontact
:
清单6.过滤数据
...
import org.xml.sax.helpers.AttributesImpl;
public class DataFilter extends XMLFilterImpl
{s
public void startElement (String namespaceUri, String localName,
String qualifiedName, Attributes attributes)
throws SAXException
{
AttributesImpl attributesImpl = new AttributesImpl(attributes);
if (localName.equals("employee")){
if (!attributes.getValue("deptid").equals("24")){
attributesImpl.setValue(3, "donotcontact");
}
}
super.startElement(namespaceUri, localName, qualifiedName, attributesImpl);
}
}
在这种情况下,您将覆盖XMLFilterImpl
定义的startElement()
方法。 它仍会继续传递该事件,但是如果雇员不在部门24中,则过滤器会将其传递给已更改的Attributes
对象,该对象将雇员列为do not contact
。
DataProcessor
对象不知道数据已被操纵。 它只是知道应该与某些雇员联系,而其他人则不应。 现在处理产生不同的结果:
Contacting employee 332
下一步
本技巧演示了使用XML过滤器更改SAX应用程序处理的简单方法。 在这种情况下,过滤器是预先确定的,但是您可以通过在运行时选择过滤器行为来构建应用程序以适应不同的情况。 您可以通过替换DataFilter
类,在运行时传递参数,甚至首先使用工厂创建过滤器类来实现此目的。
SAX应用程序还可以将过滤器链接在一起,以便将一个过滤器的输出用作另一个过滤器的输入,从而可以在模块化块中进行复杂的编程。
翻译自: https://www.ibm.com/developerworks/xml/library/x-tipsaxfilter/index.html
sax数据离散化