Моя проблема: я хотел бы проанализировать огромное количество больших 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>
...
Поскольку в вашем файле несколько XML-документов, это не совсем XML файл. Это просто файл. Таким образом, вы можете читать его с любыми файлами (например, FileReader).
Другой вариант - расширить читатель или поток и создать новый класс, который обрабатывает файлы с несколькими документами 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);
}