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

0

Моя проблема: я хотел бы проанализировать огромное количество больших 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 ФАЙЛ 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 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>
...
  • 0
    Вы пробовали: tutorialspoint.com/java_xml/java_dom_parse_document.htm ?
  • 0
    Да, я пытался. DocumentBuilder также использует функцию синтаксического анализа, которая встречается с ошибкой - файлы XML с несколькими объявлениями XML не могут быть проанализированы, потому что они не правильно сформированы.
Теги:
split
parsing

1 ответ

0

Поскольку в вашем файле несколько 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);
        }
  • 0
    Спасибо! Это именно то, что я искал!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню