Mạng xã hội
Hoặc copy link
org.xml.sax.SAXParseException; systemId: ../src/main/resources/staff.xml;
lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
Khi văn bản không hợp lệ hoặc BOM trước khai báo XML hoặc mã hóa khác sẽ gây ra SAX Error – Content is not allowed in prolog.
Ví dụ: File XML bên dưới chứa thêm một dấu chấm nhỏ ” . ” trước phần khai báo XML.
.<?xml version="1.0" encoding="utf-8"?>
<company>
<staff>
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>sharecs</nickname>
<salary>100000</salary>
</staff>
</company>
Để sửa nó: Xóa bất kỳ văn bản nào trước khai báo XML.
Nhiều trình soạn thảo văn bản tự động thêm BOM vào tệp UTF-8.
Được thử nghiệm với Java 11 và Java 8, SAX Parser tích hợp có thể phân tích cú pháp tệp BOM UTF-8 một cách chính xác; tuy nhiên, một số nhà phát triển cho rằng BOM đã gây ra lỗi khi phân tích cú pháp XML.
Để khắc phục , hãy xóa BOM khỏi tệp UTF-8.
Ví dụ dưới đây ByteBuffer để xóa BOM khỏi tệp UTF-8.
P/S: Một số trình phân tích cú pháp XML, JSON, CSV có thể không phân tích cú pháp hoặc xử lý file nếu nó chứa BOM trong tệp UTF-8; thông thường phải xóa hoặc bỏ qua BOM trước khi phân tích cú pháp tệp.
package com.sharecs.io.howto;
import org.apache.commons.codec.binary.Hex;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class RemoveBomFromUtf8File {
public static void main(String[] args) throws IOException {
Path path = Paths.get("/home/sharecs/file.txt");
writeBomFile(path, "sharecs");
removeBom(path);
}
private static void writeBomFile(Path path, String content) {
// Java 8 default UTF-8
try (BufferedWriter bw = Files.newBufferedWriter(path)) {
bw.write("\ufeff");
bw.write(content);
bw.newLine();
bw.write(content);
} catch (IOException e) {
e.printStackTrace();
}
}
private static boolean isContainBOM(Path path) throws IOException {
if (Files.notExists(path)) {
throw new IllegalArgumentException("Path: " + path + " does not exists!");
}
boolean result = false;
byte[] bom = new byte[3];
try (InputStream is = new FileInputStream(path.toFile())) {
// read 3 bytes of a file.
is.read(bom);
// BOM encoded as ef bb bf
String content = new String(Hex.encodeHex(bom));
if ("efbbbf".equalsIgnoreCase(content)) {
result = true;
}
}
return result;
}
private static void removeBom(Path path) throws IOException {
if (isContainBOM(path)) {
byte[] bytes = Files.readAllBytes(path);
ByteBuffer bb = ByteBuffer.wrap(bytes);
System.out.println("Found BOM!");
byte[] bom = new byte[3];
// get the first 3 bytes
bb.get(bom, 0, bom.length);
// remaining
byte[] contentAfterFirst3Bytes = new byte[bytes.length - 3];
bb.get(contentAfterFirst3Bytes, 0, contentAfterFirst3Bytes.length);
System.out.println("Remove the first 3 bytes, and overwrite the file!");
// override the same path
Files.write(path, contentAfterFirst3Bytes);
} else {
System.out.println("This file doesn't contains UTF-8 BOM!");
}
}
}
Kết quả
Found BOM!
Remove the first 3 bytes, and overwrite the file!
Cách mã hóa khác cũng khiến XML phổ biến Content is not allowed in prolog.
Ví dụ: file XML UTF-8.
<?xml version="1.0" encoding="utf-8"?>
<Company>
<staff id="1001">
<name>sharecs</name>
<role>support</role>
<salary currency="USD">5000</salary>
<!-- for special characters like < &, need CDATA -->
<bio><![CDATA[HTML tag <code>testing</code>]]></bio>
</staff>
<staff id="1002">
<name>yflow</name>
<role>admin</role>
<salary currency="EUR">8000</salary>
<bio><![CDATA[a & b]]></bio>
</staff>
</Company>
Và chúng ta sử dụng mã hóa UTF-16 để phân tích cú pháp tệp XML mã hóa UTF-8 ở trên.
SAXParserFactory factory = SAXParserFactory.newInstance();
try (InputStream is = getXMLFileAsStream()) {
SAXParser saxParser = factory.newSAXParser();
// parse XML and map to object, it works, but not recommend, try JAXB
MapStaffObjectHandlerSax handler = new MapStaffObjectHandlerSax();
// more options for configuration
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setContentHandler(handler);
InputSource source = new InputSource(is);
// UTF-16 to parse an UTF-8 XML file
source.setEncoding(StandardCharsets.UTF_16.toString());
xmlReader.parse(source);
// print all
List<Staff> result = handler.getResult();
result.forEach(System.out::println);
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
Kết quả
[Fatal Error] :1:1: Content is not allowed in prolog.
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1243)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:635)
at com.sharecs.xml.sax.ReadXmlSaxParser2.main(ReadXmlSaxParser2.java:45)
Cảm ơn các bạn đã ghé thăm. Chúc các bạn thành công!