Какой шаблон я должен использовать для использования парсера SAX? - PullRequest
4 голосов
/ 08 октября 2009
<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
}

Этот подход обычно делает мою функцию синтаксического анализа, содержащую начальный и конечный тег, огромной. Есть ли другой лучший подход, которому можно следовать.

Ответы [ 4 ]

5 голосов
/ 08 октября 2009

У меня был хороший опыт с этим подходом:

  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, если только скорость выполнения не важнее скорости разработки.

2 голосов
/ 08 октября 2009

Если вы хотите придерживаться явного подхода SAX, DR ответ имеет смысл. Я использовал этот подход в прошлом с успехом.

Однако вы можете взглянуть на Commons Digester , который позволяет указать объект, который будет создан / заполнен для поддеревьев XML-документа. Это очень простой способ построить иерархию объектов из XML без явного использования модели SAX.

См. эту статью ONJava для получения дополнительной информации.

0 голосов
/ 09 октября 2009

Вам необходим лексический анализатор , шаблон интерпретатора - идеальный шаблон для написания лексического анализатора.

0 голосов
/ 08 октября 2009

Вы можете создать таблицу поиска от типа к действию синтаксического анализа, а затем вам просто нужно проиндексировать свою таблицу поиска, чтобы найти соответствующее действие синтаксического анализа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...