Как разделить плохо сформированные xml-файлы по тегу объявления xml, чтобы записать его в отдельные xml-файлы для их анализа? - PullRequest
0 голосов
/ 27 января 2019

Моя проблема: я хотел бы проанализировать огромное количество больших XML-файлов и записать данные в базу данных mysql.Дело в том, что все эти XML-файлы не являются правильно сформированными, поскольку администратор объединяет несколько XML-файлов в один XML-файл и публикует их.Так что мой SAX Parser отлично работает для отдельных XML-файлов, выдает ошибку, он не может обработать XML-файл, который содержит несколько объявлений XML (xml-версия ...)

Брошенное сообщение об ошибке:

Исключение в потоке "main" org.xml.sax.SAXParseException;systemId: ..... "[xX] [mM] [lL]" .....

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE us-patent-grant SYSTEM "us-patent-grant-v42-2006-08-23.dtd" [ ]>
<us-patent-grant lang="EN" dtd-version="v4.2 2006-08-23" file="USD0535456-20070123.XML" status="PRODUCTION" id="us-patent-grant" country="US" date-produced="20070110" date-publ="20070123">
<us-bibliographic-data-grant>
<publication-reference>
<document-id>
<country>US</country>
<doc-number>D0535456</doc-number>
<kind>S1</kind>
<date>20070123</date>
</document-id>
</publication-reference>
<us-application-series-code>29</us-application-series-code>
</us-bibliographic-data-grant>
</us-patent-grant>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE us-patent-grant SYSTEM "us-patent-grant-v42-2006-08-23.dtd" [ ]>
<us-patent-grant lang="EN" dtd-version="v4.2 2006-08-23" file="USD0535457-20070123.XML" status="PRODUCTION" id="us-patent-grant" country="US" date-produced="20070110" date-publ="20070123">
<us-bibliographic-data-grant>
...

Поскольку я просматривал несколько форумов и сайтов, единственное трезвое решение - этопрочитать XML-файл, разделить его по корневому тегу и записать в отдельные XML-файлы?Как я могу читать и записывать XML-файл, не анализируя его с помощью SAX / Stax / DOM?

Результаты должны быть следующими: XML FILE 1:

?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE us-patent-grant SYSTEM "us-patent-grant-v42-2006-08-23.dtd" [ ]>
<us-patent-grant lang="EN" dtd-version="v4.2 2006-08-23" file="USD0535456-20070123.XML" status="PRODUCTION" id="us-patent-grant" country="US" date-produced="20070110" date-publ="20070123">
<us-bibliographic-data-grant>
...
</us-bibliographic-data-grant>
</us-patent-grant>

XML FILE 2:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE us-patent-grant SYSTEM "us-patent-grant-v42-2006-08-23.dtd" [ ]>
<us-patent-grant lang="EN" dtd-version="v4.2 2006-08-23" file="USD0535457-20070123.XML" status="PRODUCTION" id="us-patent-grant" country="US" date-produced="20070110" date-publ="20070123">
<us-bibliographic-data-grant>
...

1 Ответ

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

Поскольку в вашем файле несколько XML-документов, на самом деле это не XML-файл.Это просто файл.Таким образом, вы можете читать его с любыми файлами (например, FileReader).

Другой вариант - расширить читатель или поток и создать новый класс, который обрабатывает файлы с несколькими документами XML.Потребуется:

  • Возвращать конец файла при обнаружении нового XML-документа, это сообщит парсеру, что он завершен с текущим документом
  • Разрешить чтение после продолженияпсевдо конец файла, чтобы можно было прочитать следующий XML-документ
  • Дескриптор закрытия, чтобы он закрывался только при чтении всего файла, также может потребоваться какая-то опция принудительного закрытия

Что-то в этом роде ...

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

public class ConcatenatedXmlReader extends BufferedReader {

    private String nextLine = "";

    public ConcatenatedXmlReader(Reader reader, int size) {
        super(reader, size);
    }

    public ConcatenatedXmlReader(Reader reader) {
        super(reader);
    }

    private boolean seenXmlStart = false;

    // which method you need to override probably depends on which sax parser you use
    @Override
    public int read(char[] buffer, int offset, int length) throws IOException {
        readNextLine();
        if (nextLine == null) {
            return -1;
        }
        if (nextLine.startsWith("<?xml")) {
            if (seenXmlStart) {
                return -1;
            }
            seenXmlStart = true;
        }
        int addToBuffer = Math.min(nextLine.length(), length);
        for (int i = 0; i < addToBuffer; i++) {
            buffer[i] = nextLine.charAt(i);
        }
        nextLine = (addToBuffer < nextLine.length()) ? nextLine.substring(addToBuffer) : "";
        return addToBuffer;
    }

    public boolean hasXmlDocuments() throws IOException {
        readNextLine();
        seenXmlStart = false;
        return nextLine != null &&  nextLine.length() > 0;
    }

    private void readNextLine() throws IOException {
        if (nextLine != null && nextLine.length() == 0) {
            nextLine = readLine();
        }
    }

    @Override
    public void close() throws IOException {
        // override so it doesn't close the file when there are still more xml documents.
        if (nextLine != null) {
            return;
        }
        super.close();
    }

} 

Затем вы вызывали бы синтаксический анализатор несколько раз, пока в файле было больше документов xml.

например,

        SAXParserFactory factory = SAXParserFactory.newInstance();
        MyHandler handler = new MyHandler();
        ConcatenatedXmlReader reader = new ConcatenatedXmlReader(new FileReader(inputFile));
        SAXParser saxParser = factory.newSAXParser();
        while (reader.hasXmlDocuments()) {
            saxParser.parse(new InputSource(reader), handler);
        }
...