Разбор XML с BufferedReader в Java - PullRequest
0 голосов
/ 22 апреля 2020

Для начала XML файл 2,84 ГБ, и кажется, что ни один из SAX или DOM-парсеров не работает. Я уже пробовал их и каждый раз вылетает. Итак, я решил прочитать файл и экспортировать нужные данные с помощью BufferedReader, анализируя файл XML, как будто это txt.

XML Файл (небольшая часть):

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE dblp SYSTEM "dblp-2019-11-22.dtd">
<dblp>
<phdthesis mdate="2016-05-04" key="phd/dk/Heine2010">
<author>Carmen Heine</author>
<title>Modell zur Produktion von Online-Hilfen.</title>
<year>2010</year>
<school>Aarhus University</school>
<pages>1-315</pages>
<isbn>978-3-86596-263-8</isbn>
<ee>http://d-nb.info/996064095</ee>
</phdthesis><phdthesis mdate="2020-02-12" key="phd/Hoff2002">
<author>Gerd Hoff</author>
<title>Ein Verfahren zur thematisch spezialisierten Suche im Web und seine Realisierung im Prototypen HomePageSearch</title>
<year>2002</year>

Из этого файла XML я хочу получить данные, которые находятся между тегами <year>. Я также использовал Pattern и Matcher с regEx, чтобы узнать информацию, которую я хочу. Мой код на данный момент:

public class Publications {
    public static void main(String[] args) throws IOException {
        File file = new File("dblp-2020-04-01.xml");
        FileInputStream fileStream = new FileInputStream(file);
        InputStreamReader input = new InputStreamReader(fileStream);
        BufferedReader reader = new BufferedReader(input);
        String line;
        String regex = "\\d+";


        // Reading line by line from the
        // file until a null is returned
        while ((line = reader.readLine()) != null) {
            final Pattern pattern = Pattern.compile("<year>(.+?)</year>", Pattern.DOTALL);
            final Matcher matcher = pattern.matcher("<year>"+regex+"</year>");
            matcher.find();
            System.out.println(matcher.group(1)); // Prints String I want to extract
            }
        }
}

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

\d+
\d+
\d+
\d+
\d+
\d+
\d+
\d+
\d+
\d+

Есть предложения?

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

Пожалуйста, не пытайтесь анализировать XML с помощью регулярных выражений. Мы получаем сотни вопросов на этом форуме от людей, пытающихся сгенерировать XML в особых форматах, потому что это единственное, что может обработать принимающее приложение, и причина, по которой принимающее приложение имеет такие ограничения, заключается в том, что он пытается выполнить синтаксический анализ XML "рукой". Вы накапливаете проблемы для себя, для людей, с которыми хотите обмениваться данными, и для людей в StackOverflow, к которым вы обратитесь за помощью, когда все станет грушевидным. XML стандарты существуют по определенной причине и работают очень хорошо, когда все им соответствуют.

Правильный подход в этом случае - потоковый XML подход с использованием SAX, StAX или потокового XSLT 3.0, и Вы отказались от этих подходов по совершенно ложным причинам.

0 голосов
/ 22 апреля 2020

Примечание

Regexen - неправильный инструмент для извлечения информации из xml (или аналогичных структурированных форматов). Общий подход не рекомендуется. За правильный способ справиться с этим, ср. Майкл Кей ответ.

Ответ

Вы указали неверный аргумент при построении сопоставителя. Вместо выражения в вашем коде необходимо указать текущую строку:

// ...
final Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
    System.out.println(matcher.group(1)); // Prints String I want to extract
}
// ...

Обратите внимание на дополнительное условие, чтобы проверить, совпадает ли текущая строка вообще.

Также обратите внимание, что шаблон вы совпадаете с определенным в конструкторе Pattern. Таким образом, чтобы соответствовать только тегам <year>, которые содержат числовые значения, строка должна быть изменена на

final Pattern pattern = Pattern.compile("<year>(" + regex + ")</year>", Pattern.DOTALL);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...