Как бы вы использовали Java для обработки различных документов XML? - PullRequest
2 голосов
/ 27 августа 2008

Я ищу лучший способ для анализа различных документов XML с помощью приложения Java. В настоящее время я делаю это с SAX и пользовательским обработчиком контента, и он отлично работает - быстрый и стабильный.

Я решил изучить вариант, имеющий ту же программу, которая в настоящее время получает документ XML одного формата, получить два дополнительных формата документов XML с различными изменениями элементов XML. Я надеялся просто заменить ContentHandler на соответствующий, основанный на первом «startElement» в документе ... но, э-э-э, ContentHandler установлен и затем документ анализируется! 1005 *

... constructor ...
{
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser sp = spf.newSAXParser();
parser = sp.getXMLReader();
parser.setErrorHandler(new MyErrorHandler());
} catch (Exception e) {} 

... parse StringBuffer ...
try {
parser.setContentHandler(pP);
parser.parse(new InputSource(new StringReader(xml.toString())));
return true;
} catch (IOException e) {
    e.printStackTrace();
} catch (SAXException e) {
    e.printStackTrace();
}
...

Так что, похоже, я не могу сделать это так, как я изначально думал, что смогу.

Как говорится, я смотрю на это совершенно неправильно? Каков наилучший метод для анализа нескольких отдельных документов XML с одним и тем же кодом обработки XML? Я пытался спросить в более общем посте ранее ... но, мне кажется, я был слишком расплывчатым . Из соображений скорости и эффективности я никогда не смотрел на DOM, потому что эти XML-документы довольно большие, и система получает около 1200 каждые несколько минут. Это только один способ отправки информации

Чтобы сделать этот вопрос слишком длинным и добавить к моей путанице; ниже приведен макет некоторых различных XML-документов, для которых мне бы хотелось иметь один SAX, StAX или ?? С парсером чисто разобраться.

products.xml:

<products>
<product>
  <id>1</id>
  <name>Foo</name>
<product>
  <id>2</id>
  <name>bar</name>
</product>
</products>

stores.xml:

<stores>
<store>
  <id>1</id>
  <name>S1A</name>
  <location>CA</location>
</store>
<store>
  <id>2</id>
  <name>A1S</name>
  <location>NY</location>
</store>
</stores>

managers.xml:

<managers>
<manager>
  <id>1</id>
  <name>Fen</name>
  <store>1</store>
</manager>
<manager>
  <id>2</id>
  <name>Diz</name>
  <store>2</store>
</manager>
</managers>

Ответы [ 9 ]

3 голосов
/ 27 августа 2008

Насколько я понимаю, проблема в том, что вы не знаете, в каком формате находится документ до разбора. Вы можете использовать шаблон делегата. Я предполагаю, что вы не проверяете по DTD / XSD / и так далее, и это нормально для DefaultHandler, чтобы иметь состояние.

public class DelegatingHandler extends DefaultHandler {

    private Map<String, DefaultHandler> saxHandlers;
    private DefaultHandler delegate = null;

    public DelegatingHandler(Map<String, DefaultHandler> delegates) {
        saxHandlers = delegates;
    }

    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
       if(delegate == null) {
           delegate = saxHandlers.get(name);
       }
       delegate.startElement(uri, localName, name, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        delegate.endElement(uri, localName, name);
    }

//etcetera...
2 голосов
/ 27 августа 2008

См. Документацию для XMLReader.setContentHandler () , там написано:

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

Таким образом, вы должны иметь возможность создать SelectorContentHandler, который потребляет события до первого события startElement, основываясь на том, что изменяет ContentHandler в считывателе XML и передает первое событие начального элемента новому содержимому обработчик. Вам просто нужно передать XMLReader в SelectorContentHandler в конструкторе. Если вам нужно все события, которые должны быть переданы в обработчик контента для определенного словаря, SelectorContentHandler должен кэшировать события и затем передавать их, но в большинстве случаев это не нужно.

Кстати, в последнее время я использовал XOM почти во всех своих проектах для обработки XML и до сих пор производительность не была проблемой.

2 голосов
/ 27 августа 2008

Я пробовал SAXParser один раз, но как только я нашел XStream , я никогда не возвращался к нему. С XStream вы можете создавать объекты Java и конвертировать их в XML. Отправьте их и используйте XStream для воссоздания объекта. Очень простой в использовании, быстрый и создает чистый XML.

В любом случае вам нужно знать, какие данные вы собираетесь получить из XML-файла. Вы можете отправить их по-разному, чтобы узнать, какой парсер использовать. Или иметь объект данных, который может содержать все, но только одна структура заполнена (продукт / магазин / менеджеры). Может быть что-то вроде:

public class DataStructure {

    List<ProductStructure> products;

    List<StoreStructure> stors;

    List<ManagerStructure> managers;

    ...

    public int getProductCount() {
        return products.lenght();
    }

    ...
}

А с помощью XStream конвертировать в XML отправлять, а затем воссоздавать объект. Тогда делай с ней что хочешь.

2 голосов
/ 27 августа 2008

Вы проделали хорошую работу, объясняя, что вы хотите сделать, но не почему. Существует несколько платформ XML, которые упрощают маршалинг и демаршаллинг объектов Java в / из XML.

Самым простым является Commons Digester , который я обычно использую для разбора файлов конфигурации. Но если вы хотите иметь дело с объектами Java, вы должны посмотреть Castor , JiBX , JAXB , XMLBeans , XStream или что-то подобное. Кастор или JiBX - мои два фаворита.

1 голос
/ 27 августа 2008

JAXB . Архитектура Java для привязки XML. По сути, вы создаете xsd, определяющий ваш XML-макет (я думаю, вы также можете использовать DTD). Затем вы передаете XSD компилятору JAXB, и компилятор создает классы Java, чтобы маршалировать и демаршировать ваш XML-документ в объекты Java. Это действительно просто.

Кстати, в jaxb есть параметры командной строки для указания имени пакета, в который вы хотите поместить результирующие классы, и т. Д.

0 голосов
/ 09 апреля 2016

VTD-XML известен как лучшая технология обработки XML для обработки XML в тяжелых условиях. См. Ссылку ниже для доказательства

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

0 голосов
/ 27 января 2009

: -)

Да, у меня есть предвзятость в отношении Стакса. Но, как я уже сказал, привязка данных часто более удобна, чем потоковое решение. Но если вам нужна потоковая передача и не требуется конвейерная обработка (из нескольких этапов фильтрации), Stax проще, чем SAX.

Еще одна вещь: как бы ни был хорош XOM (в сравнении с альтернативами), часто Tree Model не подходит для использования, если вы не имеете дело с документно-ориентированным xml (~ = xhtml страниц, docbook, документы open office ). Для обмена данными, конфигурационными файлами и т. Д. Привязка данных более удобна, эффективна и естественна. Просто скажите «нет» древовидным моделям, таким как DOM, для этих случаев использования. Итак, JAXB, XStream, JibX хороши. Или, для более приобретенного вкуса, варочный котел, касторовое, xmlbeans.

0 голосов
/ 08 января 2009

Согласитесь со StaxMan, который достаточно интересно хочет, чтобы вы использовали Stax. Это парсер на основе пулей вместо того, что вы используете в данный момент. Это потребует значительных изменений в вашем коде.

0 голосов
/ 08 января 2009

Если вы хотите более динамичной обработки, подход Stax, вероятно, будет работать лучше, чем Sax. Это все еще довольно низкий уровень; если вы хотите более простой подход, XStream и JAXB - мои любимые. Но они требуют довольно жестких объектов для сопоставления.

...