在 GAE 上解析完全有效的 XML 时,“ Prolog 中不允许内容”

过去的48小时里,我一直在纠结这个绝对让人恼火的漏洞所以我觉得在我把笔记本电脑扔出窗外之前我最好还是认输,试着在这里问问。

我试图解析我对 AWS SimpleDB 调用的响应 XML。电线上的响应正在恢复正常; 例如,它可能看起来像:

<?xml version="1.0" encoding="utf-8"?>
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<ListDomainsResult>
<DomainName>Audio</DomainName>
<DomainName>Course</DomainName>
<DomainName>DocumentContents</DomainName>
<DomainName>LectureSet</DomainName>
<DomainName>MetaData</DomainName>
<DomainName>Professors</DomainName>
<DomainName>Tag</DomainName>
</ListDomainsResult>
<ResponseMetadata>
<RequestId>42330b4a-e134-6aec-e62a-5869ac2b4575</RequestId>
<BoxUsage>0.0000071759</BoxUsage>
</ResponseMetadata>
</ListDomainsResponse>

我将这个 XML 传递给具有

XMLEventReader eventReader = xmlInputFactory.createXMLEventReader(response.getContent());

多次调用 eventReader.nextEvent();来获取我想要的数据。

奇怪的是,它在本地服务器中运行良好。回应进来,我解析它,每个人都很高兴。问题是,当我将代码部署到 Google App Engine 时,传出的请求仍然可以工作,而响应 XML 对我来说似乎100% 相同和正确,但是响应无法解析以下异常:

com.amazonaws.http.HttpClient handleResponse: Unable to unmarshall response (ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.): <?xml version="1.0" encoding="utf-8"?>
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/"><ListDomainsResult><DomainName>Audio</DomainName><DomainName>Course</DomainName><DomainName>DocumentContents</DomainName><DomainName>LectureSet</DomainName><DomainName>MetaData</DomainName><DomainName>Professors</DomainName><DomainName>Tag</DomainName></ListDomainsResult><ResponseMetadata><RequestId>42330b4a-e134-6aec-e62a-5869ac2b4575</RequestId><BoxUsage>0.0000071759</BoxUsage></ResponseMetadata></ListDomainsResponse>
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(Unknown Source)
at com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(Unknown Source)
at com.amazonaws.transform.StaxUnmarshallerContext.nextEvent(StaxUnmarshallerContext.java:153)
... (rest of lines omitted)

我对这个 XML 进行了双重、三重、四重检查,以查找“不可见字符”或非 UTF8编码的字符,等等。我在一个字节顺序标记或类似性质的数组中逐字节地查看它。什么都没有,它通过了所有的验证测试。更奇怪的是,如果我也使用基于 Saxon 的解析器,就会发生这种情况——但是只有在 GAE 上,它才能在我的本地环境中工作得很好。

如果只能在工作完美的环境中运行调试器(我还没有找到任何在 GAE 上远程调试的好方法) ,那么就很难跟踪代码以查找问题。尽管如此,使用我已经掌握的原始方法,我已经尝试了上百万种方法,包括:

  • 有序言和没有序言的 XML
  • 不管有没有换行
  • 在 prolog 中加入和不加入“ coding =”属性
  • 都是换行样式
  • 包含和不包含 HTTP 流中存在的块信息

我已经尝试了大多数这些在多个组合中,它们有意义的互动-什么也没有!我已经无计可施了。有没有人见过这样的问题之前,希望可以提供一些线索?

谢谢!

596238 次浏览

XML 和 XSD (或 DTD)中的编码是不同的。
XML 文件头: <?xml version='1.0' encoding='utf-8'?>
XSD 文件头: <?xml version='1.0' encoding='utf-16'?>

导致这种情况的另一种可能的情况是,在 XML 文档类型声明之前出现任何东西。也就是说,缓冲区中可能有这样的东西:

helloworld<?xml version="1.0" encoding="utf-8"?>

甚至是一个空间或特殊的字符。

有一些称为字节顺序标记的特殊字符可能位于缓冲区中。 在将缓冲区传递给解析器之前,请执行以下操作..。

String xml = "<?xml ...";
xml = xml.trim().replaceFirst("^([\\W]+)<","<");

此错误消息始终是由开始元素中的无效 XML 内容引起的。例如,额外的小点“。”在 XML 元素的开头。

<?xml….”之前的任何字符都会导致以上“ 异常: prolog 中不允许内容”错误消息。

“<?xml….之前有一个小点“ .

要修复它,只需删除所有这些怪异的字符前的 “<?xml“

档号: http://www.mkyong.com/java/sax-error-content-is-not-allowed-in-prolog/

我用制表符代替了空格。 更换标签’t’修复了问题。

剪切和粘贴整个文档到一个编辑器,如记事本 + + 和显示所有字符。

我也面临着同样的问题。在我的例子中,XML 文件是从 c # 程序生成的,并输入到 AS400进行进一步处理。经过一些分析发现,我在生成 XML 文件时使用的是 UTF8编码,而 javac (在 AS400中)使用的是“ UTF8 without BOM”。 因此,必须编写与下面提到的类似的额外代码:

//create encoding with no BOM
Encoding outputEnc = new UTF8Encoding(false);
//open file with encoding
TextWriter file = new StreamWriter(filePath, false, outputEnc);


file.Write(doc.InnerXml);
file.Flush();
file.Close(); // save and close it

我在 xml 文件中遇到了同样的问题,即“ Prolog 中不允许内容”。

解决方案

最初,我的根文件夹是“ # 文件名”。

当我删除第一个字符“ #”时,错误得到了解决。

不需要删除 # filename..。 试试这样. 。

不要将 File 或 URL 对象传递给解组器方法,而是使用 FileInputStream。

File myFile = new File("........");
Object obj = unmarshaller.unmarshal(new FileInputStream(myFile));

在我的 xml 文件中,头部如下所示:

<?xml version="1.0" encoding="utf-16"? />

在一个测试文件中,我读取文件字节并将数据解码为 UTF-8(没有意识到该文件的头是 utf-16)以创建一个字符串。

byte[] data = Files.readAllBytes(Paths.get(path));
String dataString = new String(data, "UTF-8");

当我试图将这个字符串反序列化为一个对象时,我看到了同样的错误:

javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.

当我将第二行更新为

String dataString = new String(data, "UTF-16");

我能够很好地反序列化对象。因此,正如罗曼在上面提到的,编码需要匹配。

在我遇到的这个问题中,解决方案是将德语的变音符(äöü)替换为它们的 HTML 等效符号..。

以下是“ org.xml.sax.SAXParseException: Content is not allow in prolog”异常之上的原因。

  1. 首先检查 schema.xsd 和 file.xml 的文件路径。
  2. XML 和 XSD (或 DTD)中的编码应该是相同的。
    XML 文件头: <?xml version='1.0' encoding='utf-8'?>
    XSD 文件头: <?xml version='1.0' encoding='utf-8'?>
  3. 如果有任何内容出现在 XML 文档类型 Declaration ation.e: hello<?xml version='1.0' encoding='utf-16'?>之前

本着“删除所有前面的奇怪字符”的精神?下面是我的 Java 代码,它可以很好地通过 BufferedReader 处理输入:

    BufferedReader test = new BufferedReader(new InputStreamReader(fisTest));
test.mark(4);
while (true) {
int earlyChar = test.read();
System.out.println(earlyChar);
if (earlyChar == 60) {
test.reset();
break;
} else {
test.mark(4);
}
}

FWIW,我看到的字节是(十进制) : 239,187,191。

删除 xml 声明解决了这个问题

<?xml version='1.0' encoding='utf-8'?>

我在记事本 + + 中检查 xml 文件并保存文件时遇到了问题,尽管我使用了顶部的 utf-8 xml 标记作为 <?xml version="1.0" encoding="utf-8"?>

通过使用 Encoding (Tab) > Encode in UTF-8: select (was Encode in UTF-8-BOM)将文件保存在 notpad + + 中来修复

意外原因: 文件路径中的 #字符

由于一些内部错误,如果文件内容本身是100% 正确的,但您提供的文件名如 C:\Data\#22\file.xml,那么也会出现错误 在 prolog 中不允许内容

这可能也适用于其他特殊字符。

如何检查: 如果您将文件移动到一个没有特殊字符的路径中,并且错误消失,那么就是这个问题。

我今天看到了相同的错误消息。 解决方案是将文档从带 BOM 的 UTF-8更改为不带 BOM 的 UTF-8

我在 Mac OS 中压缩了 xml 并将其发送到 Windows 机器上,默认压缩会更改这些文件,因此编码会发送这条消息。

在收听 IBM MQ 时,我在使用 Spring Boot 的 @JsmListener时遇到了这种情况。我的方法接收到了 String参数,并在尝试使用 JAXB 反序列化它时得到了这个异常。

我得到的字符串似乎是 byte[].toString()的结果。是一串逗号分隔的数字。

我通过将参数类型改为 byte[]来解决这个问题,然后从中创建了一个 String:

@JmsListener(destination = "Q1")
public void receiveQ1Message(byte[] msgBytes) {
var msg = new String(msgBytes);