“Nội dung không được phép trong phần mở đầu” khi phân tích cú pháp XML hoàn toàn hợp lệ trên GAE


109

Tôi đã đập đầu với lỗi hoàn toàn tức giận này trong 48 giờ qua, vì vậy tôi nghĩ cuối cùng tôi sẽ ném chiếc khăn vào và thử hỏi ở đây trước khi ném máy tính xách tay của mình ra ngoài cửa sổ.

Tôi đang cố gắng phân tích cú pháp XML phản hồi từ cuộc gọi tôi đã thực hiện tới AWS SimpleDB. Phản hồi đang trở lại trên dây tốt; ví dụ, nó có thể giống như sau:

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

Tôi chuyển XML này cho một trình phân tích cú pháp với

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

và gọi eventReader.nextEvent();nhiều lần để lấy dữ liệu tôi muốn.

Đây là phần kỳ lạ - nó hoạt động tốt bên trong máy chủ cục bộ. Phản hồi đến, tôi phân tích cú pháp, mọi người rất vui. Vấn đề là khi tôi triển khai mã cho Google App Engine, yêu cầu gửi đi vẫn hoạt động và XML phản hồi có vẻ giống hệt và chính xác 100% đối với tôi, nhưng phản hồi không thể phân tích cú pháp với ngoại lệ sau:

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)

Tôi đã kiểm tra gấp đôi, gấp ba, gấp bốn lần XML này để tìm 'ký tự ẩn' hoặc ký tự được mã hóa không phải UTF8, v.v. Tôi đã xem xét nó từng byte trong một mảng để tìm dấu thứ tự byte hoặc thứ gì đó có tính chất như vậy. Không có gì; nó vượt qua mọi bài kiểm tra xác nhận mà tôi có thể ném vào nó. Lạ lùng hơn nữa, nó cũng xảy ra nếu tôi sử dụng trình phân tích cú pháp dựa trên Saxon - nhưng CHỈ trên GAE, nó luôn hoạt động tốt trong môi trường cục bộ của tôi.

Rất khó để theo dõi mã cho các sự cố khi tôi chỉ có thể chạy trình gỡ lỗi trên một môi trường hoạt động hoàn hảo (tôi chưa tìm thấy bất kỳ cách tốt nào để gỡ lỗi từ xa trên GAE). Tuy nhiên, bằng cách sử dụng các phương tiện ban đầu mà tôi có, tôi đã thử một triệu cách tiếp cận bao gồm:

  • XML có và không có phần mở đầu
  • Có và không có dòng mới
  • Có và không có thuộc tính "encoding =" trong phần mở đầu
  • Cả hai kiểu dòng mới
  • Có và không có thông tin phân khúc có trong luồng HTTP

Và tôi đã thử hầu hết những thứ này theo nhiều cách kết hợp mà chúng sẽ tương tác với nhau - không có gì! Tôi đã tới giới hạn của mình rồi. Có ai đã thấy một vấn đề như thế này trước đó có thể hy vọng làm sáng tỏ về nó không?

Cảm ơn!


Chúng tôi có thể sẽ cần xem thêm một số mã. Một khả năng khác là cục bộ nó không bị phân khối khi ở trên GAE. Bạn xử lý mã như thế nào trước khi chuyển nó tới trình phân tích cú pháp?
Romain Hippeau

Tôi cũng đã xem xét khả năng phân đoạn, nhưng có vẻ như không phải vậy vì thông báo lỗi mà trình phân tích cú pháp đang đưa ra chứa toàn bộ XML ngay tại đó (nó được dán ở trên). Toàn bộ mã SDK đã sửa đổi có thể được tìm thấy tại github.com/AdrianP/aws-sdk-for-java (xem các cam kết gần đây nhất) nhưng có RẤT NHIỀU mã ở đó. Tôi sẽ cố gắng tạo ra một mẫu nhỏ hơn có thể tái tạo sớm, mặc dù ngay cả điều đó cũng sẽ khó. Đó là một phần mềm phức tạp lớn ... Mặc dù vậy, cảm ơn phản hồi của bạn! :)
Adrian Petrescu


@Raedwald, tôi không nghĩ rằng đó là câu hỏi của tôi mà là trùng lặp, vì câu hỏi của tôi đã được đăng cùng kỳ năm ngoái so với một :)
Adrian Petrescu

1
Đây phải là một ví dụ về cách một câu hỏi nên được hỏi về SO, đọc qua nó đã cho tôi những hiểu biết khác nhau về cách debug như một nhà phát triển (nhờ OP)
Sudip Bhandari

Câu trả lời:


129

Mã hóa trong XML và XSD (hoặc DTD) của bạn là khác nhau.
Tiêu đề tệp XML: <?xml version='1.0' encoding='utf-8'?>
Tiêu đề tệp XSD:<?xml version='1.0' encoding='utf-16'?>

Một tình huống có thể khác gây ra điều này là khi bất kỳ thứ gì xuất hiện trước khai báo kiểu tài liệu XML. tức là bạn có thể có một cái gì đó như thế này trong bộ đệm:

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

hoặc thậm chí một khoảng trắng hoặc ký tự đặc biệt.

Có một số ký tự đặc biệt được gọi là dấu thứ tự byte có thể nằm trong bộ đệm. Trước khi chuyển bộ đệm cho Trình phân tích cú pháp, hãy làm điều này ...

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

Chào Romain, cảm ơn vì đã phản hồi! Tôi đã kiểm tra gấp đôi và gấp ba nhiều lần để tìm bất kỳ thứ gì trong bộ đệm trước đoạn mở đầu (bao gồm cả các ký tự ẩn) nhưng đơn giản là không có bất kỳ thứ gì khác ở đó. Tuy nhiên, tôi sẽ thử chuyển sang mã hóa utf-16 - vì tò mò, bạn lấy thông tin rằng XSD sử dụng UTF-16 ở đâu?
Adrian Petrescu

@Adrian Petrescu Xin lỗi, đây chỉ là những ví dụ Nếu bạn đang sử dụng DTD hoặc XSD, hãy đảm bảo chúng khớp với XML của bạn. Trước khi bạn phân tích cú pháp XML, hãy nắm bắt nó trong một Chuỗi và bao quanh nó bằng '|' và in nó ra bảng điều khiển. Điều này sẽ cho bạn biết nếu bạn đang chuyển một số ký tự phụ.
Romain Hippeau

Ah, tôi hiểu rồi :) Thật không may là tôi đã thử nó và nó không xuất hiện trong trường hợp này. Dẫu sao cũng xin cảm ơn!
Adrian Petrescu

1
Cảm ơn! Điều này cũng đã cứu tôi. xml.trim (). ReplaceFirst ("^ ([\\ W] +) <", "<");
stackoverflow

2
Ai đó vui lòng biến điều này thành câu trả lời được chấp nhận. Giải quyết vấn đề của tôi ngay lập tức. Tôi đang phân tích cú pháp Tin nhắn bắt đầu bằng "Tin nhắn: <? Xml phiên bản ...." Vấn đề là văn bản trước bit xml. Cảm ơn :)
Ric Jafe

8

Thông báo lỗi này luôn do nội dung XML không hợp lệ trong phần tử bắt đầu. Ví dụ: thêm dấu chấm nhỏ “.” ở đầu phần tử XML.

Bất kỳ ký tự nào trước “ <?xml….” sẽ gây ra thông báo lỗi “ org.xml.sax.SAXParseException: Nội dung không được phép trong bản đăng nhập ”.

Một chấm nhỏ “ . " trước“<?xml….

Để khắc phục, chỉ cần xóa tất cả các ký tự kỳ lạ trước “<?xml“.

Tham khảo: http://www.mkyong.com/java/sax-error-content-is-not-allowed-in-prolog/


3
Bạn nên đề cập đến nơi bạn đã giới thiệu rằng mkyong.com/java/sax-error-content-is-not-allowed-in-prolog
arulraj.net

5

Tôi đã phải đối mặt với cùng một vấn đề. Trong trường hợp của tôi, các tệp XML được tạo từ chương trình c # và được đưa vào AS400 để xử lý thêm. Sau một số phân tích xác định rằng tôi đang sử dụng mã hóa UTF8 trong khi tạo tệp XML trong khi javac (trong AS400) sử dụng "UTF8 không có BOM". Vì vậy, phải viết thêm mã tương tự như đã đề cập bên dưới:

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

Tôi đã gặp sự cố khi kiểm tra tệp xml trong notepad ++ và lưu tệp, mặc dù tôi có thẻ xml utf-8 hàng đầu là <?xml version="1.0" encoding="utf-8"?>

Đã khắc phục sự cố bằng cách lưu tệp trong notpad ++ với Mã hóa (Tab)> Mã hóa trong UTF-8: đã chọn (được Mã hóa trong UTF-8-BOM)


3

Xóa khai báo xml đã giải quyết được nó

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

2

Trong tệp xml của tôi, tiêu đề trông như thế này:

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

Trong một tệp thử nghiệm, tôi đang đọc các byte tệp và giải mã dữ liệu dưới dạng UTF-8 (không nhận ra tiêu đề trong tệp này là utf-16) để tạo một chuỗi.

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

Khi tôi cố gắng giải mã chuỗi này thành một đối tượng, tôi gặp lỗi tương tự:

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

Khi tôi cập nhật dòng thứ hai thành

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

Tôi đã có thể deserialize đối tượng tốt. Vì vậy, như Romain đã lưu ý ở trên, các bảng mã cần phải khớp.


1

Tôi đã gặp phải vấn đề tương tự được gọi là "Nội dung không được phép trong prolog" trong tệp xml của tôi.

Giải pháp

Ban đầu thư mục gốc của tôi là '# Filename '.

Khi tôi xóa ký tự đầu tiên '#', lỗi đã được giải quyết.

Không cần xóa #filename ... Hãy thử theo cách này ..

Thay vì chuyển một đối tượng Tệp hoặc URL tới phương thức bộ giải nén, hãy sử dụng một FileInputStream.

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

1

Lý do không mong muốn: #ký tự trong đường dẫn tệp

Do một số lỗi nội bộ, lỗi Nội dung không được phép trong prolog cũng xuất hiện nếu nội dung tệp chính xác 100% nhưng bạn đang cung cấp tên tệp như C:\Data\#22\file.xml.

Điều này cũng có thể áp dụng cho các ký tự đặc biệt khác.

Cách kiểm tra: Nếu bạn di chuyển tệp của mình vào một đường dẫn không có ký tự đặc biệt và lỗi biến mất, thì đó là vấn đề này.


1

Tôi đã gặp thông báo lỗi tương tự ngày hôm nay. Giải pháp là thay đổi tài liệu từ UTF-8 có BOM thành UTF-8 không có BOM


Tôi gặp vấn đề tương tự. Thay đổi định dạng tệp đã giải quyết được sự cố. Cảm ơn!
code_fish

0

Tôi đã có một ký tự tab thay vì dấu cách. Thay thế tab '\ t' đã khắc phục được sự cố.

Cắt và dán toàn bộ tài liệu vào một trình soạn thảo như Notepad ++ và hiển thị tất cả các ký tự.


0

Trong trường hợp của tôi về vấn đề, giải pháp là thay thế âm sắc tiếng Đức (äöü) bằng các từ tương đương HTML của chúng ...


0

dưới đây là nguyên nhân ở trên “org.xml.sax.SAXParseException: Nội dung không được phép trong ngoại lệ”.

  1. Đầu tiên hãy kiểm tra đường dẫn tệp của schema.xsd và file.xml.
  2. Mã hóa trong XML và XSD (hoặc DTD) của bạn phải giống nhau.
    Tiêu đề tệp XML: <?xml version='1.0' encoding='utf-8'?>
    Tiêu đề tệp XSD:<?xml version='1.0' encoding='utf-8'?>
  3. nếu bất cứ điều gì xuất hiện trước khai báo kiểu tài liệu XML .ie: hello<?xml version='1.0' encoding='utf-16'?>

0

Với tinh thần "chỉ cần xóa tất cả các ký tự kỳ lạ đó trước <? Xml", đây là mã Java của tôi, mã này hoạt động tốt với đầu vào thông qua 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, số byte tôi đang thấy là (ở dạng thập phân): 239, 187, 191.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.