sax数据离散化_使用SAX筛选器来处理数据

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实际上解析该文档,并将诸如startElementendDocument事件发送到内容处理程序。 您可以将错误发送到单独的错误处理程序对象。 处理程序对象接收这些事件并对其进行操作。

主应用程序还可以充当内容或错误处理程序(或两者),但是在清单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数据离散化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值