быстрое извлечение данных из XML

У меня есть образец xml

<?xml version="1.0" encoding="UTF-8"?>
  <tag_1>
     <tag_2>A</tag_2>
     <tag_3>B</tag_3>
     <tag_4>C</tag_4>
     <tag_5>D</tag_5>
  </tag_1>
</xml>

Теперь мне интересно извлекать только определенные данные.

Например

tag_1/tag_5 -> D

tag_1/tag_5 - это мое определение данных (единственные данные, которые мне нужны), которое является динамическим по своей природе, что означает, что завтра tag_1/tag_4 будет моим определением данных.

Так что на самом деле мой xml представляет собой большой набор данных. И эти полезные нагрузки xml составляют от 50 000 до 80 000 в час.

Я хотел бы знать, есть ли уже высокопроизводительный инструмент для чтения xml или какая-то специальная логика, которую я могу реализовать, которая извлекает данные в зависимости от определения данных.

В настоящее время у меня есть реализация с использованием синтаксического анализатора Stax, но для анализа 80 000 xml требуется почти день.

public class VTDParser {

    private final Logger LOG = LoggerFactory.getLogger(VTDParser.class);

    private final VTDGen vg;

    public VTDParser() {
        vg = new VTDGen();
    }

    public String parse(final String data, final String xpath) {
        vg.setDoc(data.getBytes());
        try {
            vg.parse(true);
        } catch (final ParseException e) {
            LOG.error(e.toString());
        }

        final VTDNav vn = vg.getNav();
        final AutoPilot ap = new AutoPilot(vn);
        try {
            ap.selectXPath(xpath);
        } catch (final XPathParseException e) {
            LOG.error(e.toString());
        }

        try {
            while (ap.evalXPath() != -1) {
                final int val = vn.getText();
                if (val != -1) {
                    return vn.toNormalizedString(val);
                }
            }
        } catch (XPathEvalException | NavException e) {
            LOG.error(e.toString());
        }
        return null;
    }
}

person Saurabh Kumar    schedule 09.01.2017    source источник
comment
Не уверен, почему я получил -1. Я не ясно? Я просто ищу идеи и не прошу кого-то реализовать для меня.   -  person Saurabh Kumar    schedule 10.01.2017
comment
50-80 000/час, то есть 20 в секунду. Если вы работаете только в однопоточном режиме, это означает 1/20 секунды для одного xml. Если файлы xml очень большие, как вы говорите, вы никогда не сможете проанализировать их в течение 0,05 секунд, тем более что это могут быть другие накладные расходы, которые вы, вероятно, не можете контролировать (например, задержка сети/диска при чтении файлов xml). Итак, чтобы достичь своей цели, вам сначала нужно распараллелить работу. А затем, вероятно, подумайте о том, чтобы поместить данные в базу данных для упрощения запросов, чтобы вам не пришлось повторно анализировать все документы, когда ваш запрос изменится завтра. Но базу данных тоже нужно планировать   -  person cello    schedule 10.01.2017
comment
Да сэр. На самом деле я реализовал наконец, используя Vtd-Xml. Мне тоже не терпится услышать ваш ответ.   -  person Saurabh Kumar    schedule 12.01.2017
comment
хорошо, я отправлю фрагмент кода, следите за обновлениями...   -  person vtd-xml-author    schedule 14.01.2017
comment
@vtd-xml-author, поэтому я разместил код. Я вижу одну проблему, если я создаю только один экземпляр VTDParser и продолжаю вызывать метод разбора VTDParser, чем vg.getNav() заканчивается каким-то исключением. Не видно, потому что используется многопоточность и завернуто в Future. Только первый вызов заканчивается успехом, все остальные заканчиваются каким-то исключением.   -  person Saurabh Kumar    schedule 15.01.2017
comment
насколько велики ваши xmls в среднем?   -  person vtd-xml-author    schedule 15.01.2017
comment
Привет... XML-файлы тоже могут быть маленькими или очень большими (SAP IDOC). Итак, что я пытался сделать, так это создать один VDTParser для одного XML и, используя несколько потребительских потоков, выполнить xpath для этого одного парсера. Поскольку он не работает, я создаю новый VTDParser для каждого нового потребительского потока, но меня это не устраивает, поскольку, например, если у меня есть 100 xpaths, я закончу тем, что создам 100 экземпляров VDTParser. Как мы можем избежать этого? Также сколько ресурсов требуется для создания, когда я делаю final VTDGen vg = new VTDGen();   -  person Saurabh Kumar    schedule 15.01.2017
comment
хорошо, я вижу, что ваше требование не так просто, как я ожидал изначально.... это будет длинная переписка   -  person vtd-xml-author    schedule 17.01.2017
comment
Вы знаете, как повторно использовать выражение xpath?   -  person vtd-xml-author    schedule 17.01.2017
comment
Привет. Я разместил свой код выше. Теперь отдельный поток переходит к методу синтаксического анализа. Не могли бы вы рассказать, как повторно использовать xpath и VTDgen в коде выше?   -  person Saurabh Kumar    schedule 17.01.2017


Ответы (1)


Это мой мод для вашего кода, который компилирует xpath один раз и повторно использует много раз. Он компилирует xpath без привязки к экземпляру VTDNav. Он также вызывает resetXPath перед выходом из метода синтаксического анализа. Я, однако, не показывал вам, как предварительно индексировать документы xml с помощью VTD... чтобы избежать повторного синтаксического анализа... и я подозреваю, что это может иметь значение для вашего проект... Вот ссылка на документ о возможностях vtd-xml..

http://recipp.ipp.pt/bitstream/10400.22/1847/1/ART_BrunoOliveira_2013.pdf

import com.ximpleware.*;


public class VTDParser {
      // private final Logger LOG = LoggerFactory.getLogger(VTDParser.class);

        private final VTDGen vg;
        private final AutoPilot ap;
        public VTDParser() throws VTDException{
            vg = new VTDGen();
            ap = new AutoPilot();
            ap.selectXPath("/a/b/c");// this is how you compile xpath w/o binding to an XML doc
        }

        public String parse(final String data, final AutoPilot ap1) {
            vg.setDoc(data.getBytes());
            try {
                vg.parse(true);
            } catch (final ParseException e) {
                LOG.error(e.toString());
            }

            final VTDNav vn = vg.getNav();
            ap1.bind(vn);
            try {
                while (ap.evalXPath() != -1) {
                    final int val = vn.getText();
                    if (val != -1) {
                        return vn.toNormalizedString(val);
                    }
                }
            } catch (XPathEvalException | NavException e) {
                LOG.error(e.toString());
            }
            ap.resetXPath();// reset your xpath here
            return null;
        }
}
person vtd-xml-author    schedule 18.01.2017
comment
Спасибо. Я не понял, почему мы передали AutoPilot ap1 в качестве параметра для разбора, а затем вызвали bind(vn) - person Saurabh Kumar; 19.01.2017
comment
это потому, что вы хотите повторно использовать выражение xpath... верно? если вы передаете строку, это больше не используется повторно... - person vtd-xml-author; 19.01.2017
comment
Привет. Я хочу знать, можем ли мы иметь что-то вроде этого /Anythere here/A/B/C. А, В, С всегда рядом. - person Saurabh Kumar; 14.02.2017
comment
не понял вашего вопроса, можете создать отдельную тему и подробнее? - person vtd-xml-author; 14.02.2017
comment
вы имели в виду /*/A/B/C? - person vtd-xml-author; 15.02.2017
comment
да.. можно? могу ли я использовать что-то подобное - person Saurabh Kumar; 17.02.2017
comment
да, это просто xpath... почему бы и нет? вам удобно с xpath? - person vtd-xml-author; 17.02.2017