Как повысить производительность запросов к XML-файлам с помощью VTD-XML и XPath? - PullRequest
0 голосов
/ 15 апреля 2019

Я запрашиваю XML-файлы размером около 1 МБ (20 000+ строк).Я использую XPath для описания того, что я хочу получить, и библиотеку VTD-XML, чтобы получить это.Я думаю, что у меня есть некоторые проблемы с производительностью.

Проблема в том, что я делаю около 5k + запросов к XML-файлу.Требуется приблизительно 16-17 секунд, чтобы получить все значения.Я хочу спросить вас, нормально ли это для такой задачи?Как я могу улучшить его?

Я использую библиотеку VTD-XML с навигационным подходом AutoPilot, который дает мне возможность использовать XPath.Реализация следующая:

private VTDGen vg = new VTDGen();
private VTDNav vn;
private AutoPilot ap = new AutoPilot();

public void init(String xml) {
    log.info("Creating document");
    xml = xml.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    byte[] bytes = xml.getBytes(StandardCharsets.UTF_8);
    vg.setDoc(bytes);
    try {
        vg.parse(true);
        vn = vg.getNav();
    } catch (ParseException e) {
        e.printStackTrace();
    }
    log.info("Document created");
}

public String parseXmlOrReturnNull(String query) {
    String xPathStringVal = null;
    try {
        ap.selectXPath(query);
        ap.bind(vn);
        int i = -1;
        while ((i = ap.evalXPath()) != -1) {
            xPathStringVal = vn.getXPathStringVal();
        }
    }catch (XPathEvalException e) {
        e.printStackTrace();
    } catch (NavException e) {
        e.printStackTrace();
    } catch (XPathParseException e) {
        e.printStackTrace();
    }
    return xPathStringVal;
}

Мои XML-файлы имеют определенный формат, они разделены на множество частей - сегментов, и мои запросы одинаковы для всех сегментов (я запрашиваю его в цикле).Например, часть xml:

<segment>
    <a>
        <b>value1</b>
        <c>
            <d>value2</d>
            <e>value3</d>
        </c>
    </a>
</segment>
<segment>
    <a>
        <b>value4</b>
        <c>
            <d>value5</d>
            <e>value6</d>
            <f>value6</d>
        </c>
    </a>
</segment>
...

Если я хочу получить значение 1 в первом сегменте, я использую запрос:

//segment[1]/a/b

для значения 4 во втором сегменте

//segment[2]/a/b

и т. Д.

Интуиция говорит о нескольких вещах: в моем подходе каждый запрос независим (он ничего не знает о другом запросе), это означает, что AutoPilot, мой итератор, всегда запускается в началефайл, когда я хочу запросить его.

Мой вопрос: есть ли способ установить AutoPilot в начале сегмента обработки?И когда я закончу запросы, переместу AutoPilot в следующий сегмент?Я думаю, что если мой метод начнет поиск значения не с начала, а с заданной точки, это будет намного быстрее.

Другой способ - разделить файл XML на небольшие файлы XML (один файл XML = один сегмент) изапрашивать эти небольшие XML-файлы.

Как вы думаете, ребята?Заранее спасибо

1 Ответ

0 голосов
/ 15 апреля 2019

Незначительный: замена не требуется, поскольку UTF-8 является кодировкой по умолчанию; только когда является кодировкой, нужно будет подключить его к UTF-8.

XPath следует выполнять только один раз, чтобы не начинать с [0] до следующего индекса.

Если вам нужно представление List, вы можете использовать JAXB с аннотациями.

Анализ примитивов на основе событий без Объект DOM, вероятно, является лучшим (SAXParser).

Handler handler = new org.xml.sax.helpers.DefaultHandler {
    @Override
    public void startElement(String uri, 
        String localName, String qName, Attributes attributes) throws SAXException {
    }

    @Override
    public void endElement(String uri, 
        String localName, String qName) throws SAXException {
    }

    @Override
    public void characters(char ch[], int start, int length) throws SAXException {
    }
};
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
InputStream in = new ByteArrayInputStream(bytes);
parser.parse(in, handler);
...