java - 我应该使用什么模式来使用 SAX 解析器?

标签 java design-patterns oop

<xml>
<Office prop1="prop1" prop2="prop2">
    <Version major="1" minor="0"/>
    <Label>MyObjectA</Label>
    <Active>No</Active>
</Office>
<Vehicle prop="prop">
    <Wheels>4</Wheels>
    <Brand>Honda</Brand>
    <Bought>No</Bought>
</Vehicle>
</xml>

我的 XML 就是这种格式。我正在使用 SAX 解析器解析此文件,因为 xml 文件的大小可能很大。

我应该遵循什么模式来解析文件。

通常我一直遵循这种方法:

//PseudoCode
if(start){
    if(type Office)
    {
       create an instance of type Office and populate the attributes of Office in the Office class using a call back
    }
    if(type Vehicle)
    {
       create an instance of type Vehicle and populate the attributes of Vehicle in the Vehicle class using a call back
     }
}

if(end){
     // do cleaning up
}

这种方法通常会使包含开始和结束标记的解析函数变得庞大。 有没有其他更好的方法可以遵循。

最佳答案

我对这种方法有很好的经验:

  1. 创建查找表以将节点名称映射到处理函数。您很可能需要为每个节点名称维护两个处理程序,一个用于开始标记,一个用于结束标记。
  2. 维护父节点堆栈。
  3. 从查找表调用处理程序。
  4. 每个处理函数都可以在没有进一步检查的情况下完成它的任务。但如果有必要,每个处理程序也可以通过查看父节点堆栈来确定当前上下文。如果您在节点层次结构的不同位置有同名节点,这一点就变得很重要。

一些伪Java代码:

public class MyHandler extends DefaultHandler {

private Map<String, MyCallbackAdapter> startLookup = new HashMap<String, MyCallbackAdapter>();
private Map<String, MyCallbackAdapter> endLookup = new HashMap<String, MyCallbackAdapter>();
private Stack<String> nodeStack = new Stack<String>();

public MyHandler() {
   // Initialize the lookup tables
   startLookup.put("Office", new MyCallbackAdapter() { 
      public void execute() { myOfficeStart() } 
    });

   endLookup.put("Office", new MyCallbackAdapter() { 
      public void execute() { myOfficeEnd() } 
    });
}

public void startElement(String namespaceURI, String localName,
        String qName, Attributes atts) {
  nodeStack.push(localName);

  MyCallbackAdapter callback = startLookup.get(localName);
  if (callback != null)
    callback.execute();
}

public void endElement(String namespaceURI, String localName, String qName)

  MyCallbackAdapter callback = endLookup.get(localName);
  if (callback != null)
    callback.execute();

  nodeStack.pop();
}

private void myOfficeStart() {
  // Do the stuff necessary for the "Office" start tag
}

private void myOfficeEnd() {
  // Do the stuff necessary for the "Office" end tag
}

//...

一般建议: 根据您的要求,您可能需要进一步的上下文信息,例如先前的节点名称或当前节点是否为空。如果您发现自己添加了越来越多的上下文信息,您可能会考虑切换到完整的 DOM 解析器,除非运行时速度比开发速度更重要。

关于java - 我应该使用什么模式来使用 SAX 解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1537136/

相关文章:

c++ - 这是 "recognised"OO 模式吗?需要健全性检查!

javascript - 对面向对象的javascript的困惑

java - Disruptor - 环形缓冲区

java - 分页 MySQL 数据库结果

java - Ant build.xml 导致 java.io.IOException : System cannot find the specified file

spring - 如何在AOP中实现策略模式

关于数据封装的C#设计问题

jdbc - 从 jdbc ResultSet 填充类

ruby-on-rails - Ruby on Rails Active Record 验证 "Draft"状态最佳实践

javascript - 如何在此 javascript 中使用 html 标签?