Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Выделение структуры документа


Автор: serious 15.4.2008, 13:47
Есть документ вида:

Код

дата, должностное лицо и т.д. (т.е. реквизиты)

Название (может быть многострочным)

Раздел 1. Название раздела 1
Подраздел 1. Название подраздела 1
Глава 1. Название главы 1

...

Раздел N. Название раздела N
Подраздел N. Название подраздела N
Глава N. Название главы N


Некоторые части окумента опциональны, т.е. раздела или подраздела может и не быть, а вместо этого сразу начинаться глава.

Как представить такой документ в виде иерархии объектов? Пробовал делать при помощи регулярного выражения, но оно получается слишком большим и толком не работает...

Автор: maxim1000 15.4.2008, 15:23
тут можно сделать что-то вроде автомата со своим состоянием и идти ним по документу, постепенно строя дерево

т.е. сначала у дерева только корень
его и делаем текущим узлом
когда встречаем какой-то отдельный объект документа (раздел/подраздел/глава), смотрим на текущий узел, если найденный объект по уровню ниже текущего, добавляем его, как элемент этого текущего, если такой же по уровню или выше - делаем текущим родителя текущего узла и повторяем анализ найденного объекта

т.е. что-то типа такого:
Код

Node *currentNode=root;
Object *detectedObject=document.GetNext();
while(document.IsNotCompleted())
{
    if(detectedObject->IsInsertable(currentNode))
    {
        currentNode=currentNode->AddChild(detectedObject);
        detectedObject=document.GetNext();
    }
    else
        currentNode=currentNode->Parent;
}


Автор: serious 15.4.2008, 16:07
Я сделал что-то вроде этого, но теперь не знаю, как избавиться от недостатков:
  •  Каждая строка документа проверяется всеми регулярными выражениями.
  •  Непонятно, как анализировать названия, состоящие из нескольких строк.


Код

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class AbstractDocumentMatcher {

    private final Pattern pattern;
    private AbstractDocumentMatcher childMatcher;
    private AbstractDocument currentDocument;

    private List<AbstractDocument> documents = new ArrayList<AbstractDocument>();

    protected abstract AbstractDocument createDocument(Matcher matcher);

    public AbstractDocumentMatcher(AbstractRegex regex) {
        pattern = regex.getPattern();
    }

    public Pattern getPattern() {
        return pattern;
    }

    AbstractDocument getCurrentDocument() {
        return currentDocument;
    }

    public void parseLine(String line) {
        getDocumentFromLine(line);
    }

    private AbstractDocument getDocumentFromLine(String line) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            currentDocument = createDocument(matcher);
            documents.add(currentDocument);
            return currentDocument;
        } else {
            if (childMatcher == null) {
                if (currentDocument != null) {
                    currentDocument.addLine(line);
                }
            } else {
                AbstractDocument childDocument = childMatcher.getDocumentFromLine(line);
                if (childDocument != null && currentDocument != null) {
                    currentDocument.addChild(childDocument);
                }
            }
            return null;
        }
    }

    public void setChild(AbstractDocumentMatcher child) {
        this.childMatcher = child;
    }

    public List<AbstractDocument> getDocuments() {
        return Collections.unmodifiableList(documents);
    }
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)