【问题标题】:"Content is not allowed in prolog" when parsing perfectly valid XML on GAE在 GAE 上解析完全有效的 XML 时,“prolog 中不允许有内容”
【发布时间】:2011-03-03 03:13:33
【问题描述】:

在过去的 48 小时里,我一直在与这个绝对令人愤怒的 bug 搏斗,所以我想我最终还是认输并尝试在这里询问,然后再将笔记本电脑扔出窗外。

我正在尝试解析来自我对 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 中有和没有“encoding=”属性
  • 两种换行样式
  • HTTP 流中存在和不存在分块信息

而且我已经在多种组合中尝试了其中的大多数,它们可以交互 - 没有!我无计可施。有没有人在此之前看到过这样的问题,希望能对此有所了解?

谢谢!

【问题讨论】:

  • 我们可能需要查看更多代码。另一种可能性是在本地它没有被分块,而在 GAE 上它是。在将代码传递给解析器之前,您是如何处理代码的?
  • 我也考虑了分块的可能性,但似乎并非如此,因为解析器抛出的错误消息包含整个 XML 就在那里(它已粘贴在上面)。整个修改后的 SDK 代码可以在 github.com/AdrianP/aws-sdk-for-java 找到(查看最近的提交),但是那里有很多代码。我会尽快尝试创建一个更小的可重现样本,尽管即使那样也很难。这是一个非常复杂的软件......不过感谢您的反馈! :)
  • @Raedwald,我不认为我的问题是重复的,因为我的问题比那个问题早一年发布:)
  • 这应该是一个应该如何在 SO 上提出问题的示例,通读它给了我关于如何作为开发人员进行调试的各种见解(感谢 OP)

标签: java xml google-app-engine parsing stax


【解决方案1】:

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

导致这种情况的另一种可能情况是在 XML 文档类型声明之前有任何内容。即你可能在缓冲区中有这样的东西:

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

甚至是空格或特殊字符。

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

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

【讨论】:

  • 您好罗曼,感谢您的回复!在序言之前,我已经对缓冲区中的任何内容(包括隐藏字符)进行了多次和三次检查,但那里根本没有任何其他内容。不过,我将尝试切换到 utf-16 编码——出于好奇,您从哪里获得 XSD 使用 UTF-16 的信息?
  • @Adrian Petrescu 抱歉,这些只是示例 如果您使用的是 DTD 或 XSD,请确保它们与您的 XML 匹配。在解析 XML 之前,将其捕获为字符串并用“|”括起来并将其打印到控制台。这将告诉您是否传递了一些额外的字符。
  • 啊,我明白了 :) 不幸的是,我试过了,但在这种情况下似乎并非如此。还是谢谢!
  • 谢谢!这也救了我。 xml.trim().replaceFirst("^([\\W]+)
  • 有人请将此作为接受的答案。直接解决了我的问题。我正在解析以“消息:
【解决方案2】:

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

&lt;?xml….”之前的任何字符都会导致上述“org.xml.sax.SAXParseException: Content is not allowed in prolog”错误消息。

“&lt;?xml…. 之前的小点“.

要修复它,只需删除 “&lt;?xml“ 之前的所有奇怪字符。

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

【讨论】:

【解决方案3】:

我有一个制表符而不是空格。 替换选项卡 '\t' 解决了问题。

将整个文档剪切并粘贴到 Notepad++ 等编辑器中并显示所有字符。

【讨论】:

    【解决方案4】:

    我遇到了同样的问题。在我的例子中,XML 文件是从 c# 程序生成的,并被送入 AS400 进行进一步处理。经过一些分析确定我在生成 XML 文件时使用了 UTF8 编码,而 javac(在 AS400 中)使用“没有 BOM 的 UTF8”。 因此,不得不编写类似于下面提到的额外代码:

    //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
    

    【讨论】:

      【解决方案5】:

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

      解决方案

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

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

      无需删除#filename... 用这种方法试试。。

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

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

      【讨论】:

        【解决方案6】:

        在我的 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");
        

        我能够很好地反序列化对象。所以正如 Romain 上面提到的,编码需要匹配。

        【讨论】:

          【解决方案7】:

          在我的问题实例中,解决方案是将德语变音符号 (äöü) 替换为其 HTML 等效项...

          【讨论】:

            【解决方案8】:

            下面是“org.xml.sax.SAXParseException: Content is not allowed in prolog”异常的原因。

            1. 首先检查schema.xsd和file.xml的文件路径。
            2. XML 和 XSD(或 DTD)中的编码应该相同。
              XML 文件头:&lt;?xml version='1.0' encoding='utf-8'?&gt;
              XSD 文件头:&lt;?xml version='1.0' encoding='utf-8'?&gt;
            3. 如果在 XML 文档类型声明之前有任何内容。即:hello&lt;?xml version='1.0' encoding='utf-16'?&gt;

            【讨论】:

              【解决方案9】:

              本着“删除

                  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。

              【讨论】:

                【解决方案10】:

                删除 xml 声明解决了它

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

                【讨论】:

                  【解决方案11】:

                  我在 notepad++ 中检查 xml 文件并保存文件时遇到了问题,尽管我的顶部 utf-8 xml 标记为 &lt;?xml version="1.0" encoding="utf-8"?&gt;

                  通过使用 Encoding(Tab) 将文件保存在 notpad++ 中得到修复 > 在 UTF-8 中编码:已选择(在 UTF-8-BOM 中编码)

                  【讨论】:

                    【解决方案12】:

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

                    由于一些内部错误,如果文件内容本身 100% 正确但您提供的文件名如C:\Data\#22\file.xml.

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

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

                    【讨论】:

                      【解决方案13】:

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

                      【讨论】:

                      • 我遇到了同样的问题。更改文件格式解决了这个问题。谢谢!
                      【解决方案14】:

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

                      【讨论】:

                        猜你喜欢
                        • 2016-11-28
                        • 2011-10-23
                        • 2011-06-19
                        • 2023-04-06
                        • 1970-01-01
                        • 2016-09-06
                        • 1970-01-01
                        • 2015-11-15
                        • 1970-01-01
                        相关资源
                        最近更新 更多