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

StackOverflow https://stackoverflow.com/questions/30627

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

... 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 или ??парсер чисто разбирается.

продукты.xml:

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

магазины.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>

менеджеры.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>
Это было полезно?

Решение

Насколько я понимаю, проблема в том, что до парсинга вы не знаете, в каком формате документ.Вы можете использовать шаблон делегата.Я предполагаю, что вы не проверяете DTD/XSD/etcetera и что 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...

Другие советы

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

Самое простое это Общий дайджест который я обычно использую для анализа файлов конфигурации.Но если вы хотите иметь дело с объектами Java, вам следует посмотреть Кастор, ДжиБХ, ЯКСБ, XMLBeans, XStream, или что-то подобное.Castor или JiBX — мои любимые.

Я однажды попробовал 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 отправить, а затем воссоздать объект.Тогда делайте с ним что хотите.

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

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

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

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

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

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

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

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

:-)

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top