“ ไม่อนุญาตให้มีเนื้อหาใน prolog” เมื่อแยกวิเคราะห์ XML ที่ถูกต้องสมบูรณ์บน GAE


109

ฉันทุบหัวตัวเองกับข้อผิดพลาดที่ทำให้โกรธมากในช่วง 48 ชั่วโมงที่ผ่านมาดังนั้นฉันคิดว่าในที่สุดฉันก็โยนผ้าเช็ดตัวและลองถามที่นี่ก่อนที่จะโยนแล็ปท็อปออกไปนอกหน้าต่าง

ฉันกำลังพยายามแยกวิเคราะห์ XML การตอบกลับจากการโทรไปยัง AWS SimpleDB การตอบสนองกลับมาที่สายได้ดี ตัวอย่างเช่นอาจมีลักษณะดังนี้:

<?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 เป็นต้นฉันดูที่มันเป็นไบต์ต่อไบต์ในอาร์เรย์เพื่อหาเครื่องหมายไบต์ตามลำดับหรือบางอย่างในลักษณะนั้น ไม่มีอะไร; มันผ่านการทดสอบการตรวจสอบความถูกต้องทุกครั้งที่ฉันสามารถทำได้ แม้แต่คนแปลกหน้าก็เกิดขึ้นได้หากฉันใช้ตัวแยกวิเคราะห์ที่ใช้แซกซอนเช่นกัน - แต่เฉพาะใน GAE เท่านั้นที่ทำงานได้ดีในสภาพแวดล้อมในท้องถิ่นของฉัน

ทำให้ยากมากที่จะติดตามโค้ดเพื่อหาปัญหาเมื่อฉันสามารถเรียกใช้ดีบักเกอร์ในสภาพแวดล้อมที่ทำงานได้อย่างสมบูรณ์เท่านั้น (ฉันไม่พบวิธีที่ดีในการดีบักจากระยะไกลบน GAE) อย่างไรก็ตามการใช้วิธีการดั้งเดิมที่ฉันมีฉันได้ลองวิธีการนับล้าน ได้แก่ :

  • XML ที่มีและไม่มี prolog
  • มีและไม่มีบรรทัดใหม่
  • มีและไม่มีแอตทริบิวต์ "encoding =" ใน prolog
  • ทั้งรูปแบบขึ้นบรรทัดใหม่
  • มีและไม่มีข้อมูลการแบ่งส่วนที่มีอยู่ในสตรีม HTTP

และฉันได้ลองสิ่งเหล่านี้เกือบทั้งหมดในหลาย ๆ ชุดซึ่งมันสมเหตุสมผลแล้วที่พวกเขาจะโต้ตอบ - ไม่มีอะไร! ฉันสิ้นปัญญาแล้ว มีใครเคยเห็นปัญหาเช่นนี้มาก่อนซึ่งหวังว่าจะได้รับความกระจ่างบ้าง?

ขอบคุณ!


เราอาจจะต้องดูโค้ดเพิ่มเติม ความเป็นไปได้อีกประการหนึ่งคือในพื้นที่จะไม่ได้รับการแยกชิ้นส่วนในขณะที่ใช้ GAE คุณจัดการโค้ดอย่างไรก่อนที่จะส่งต่อไปยังโปรแกรมแยกวิเคราะห์
Romain Hippeau

ฉันพิจารณาความเป็นไปได้ในการแบ่งส่วนเช่นกัน แต่ดูเหมือนจะไม่เป็นเช่นนั้นเนื่องจากข้อความแสดงข้อผิดพลาดที่โปรแกรมแยกวิเคราะห์กำลังขว้างมี XML ทั้งหมดอยู่ที่นั่น (วางไว้ด้านบน) รหัส SDK ที่แก้ไขทั้งหมดสามารถพบได้ที่github.com/AdrianP/aws-sdk-for-java (ดูการกระทำล่าสุด) แต่มีโค้ดจำนวนมากที่นั่น ฉันจะพยายามสร้างตัวอย่างที่ทำซ้ำได้ขนาดเล็กในเร็ว ๆ นี้แม้ว่ามันจะยากก็ตาม เป็นซอฟต์แวร์ที่ซับซ้อนขนาดใหญ่ ... ขอบคุณสำหรับคำติชมของคุณ! :)
Adrian Petrescu


@Raedwald ฉันไม่คิดว่ามันเป็นคำถามของฉันที่ซ้ำกันเนื่องจากคำถามของฉันถูกโพสต์เมื่อหนึ่งปีก่อนหน้านั้น :)
Adrian Petrescu

1
นี่ควรเป็นตัวอย่างของการถามคำถามเกี่ยวกับ SO การอ่านมันทำให้ฉันได้รับข้อมูลเชิงลึกต่างๆเกี่ยวกับวิธีการดีบักในฐานะนักพัฒนา (ขอบคุณ OP)
Sudip Bhandari

คำตอบ:


129

การเข้ารหัสใน 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"?>  

หรือแม้แต่ช่องว่างหรืออักขระพิเศษ

มีอักขระพิเศษบางตัวที่เรียกว่าเครื่องหมายลำดับไบต์ที่อาจอยู่ในบัฟเฟอร์ ก่อนที่จะส่งบัฟเฟอร์ไปยัง Parser ให้ทำสิ่งนี้ ...

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

สวัสดี Romain ขอบคุณสำหรับการตอบกลับ! ฉันตรวจสอบสองครั้งและสามครั้งหลายครั้งสำหรับสิ่งใด ๆ ในบัฟเฟอร์ก่อนที่จะมี prolog (รวมถึงอักขระที่ซ่อนอยู่) แต่ไม่มีสิ่งอื่นใดที่นั่น ฉันจะลองเปลี่ยนไปใช้การเข้ารหัส utf-16 - ด้วยความอยากรู้อยากเห็นคุณได้ข้อมูลที่ XSD ใช้ UTF-16 มาจากไหน
Adrian Petrescu

@Adrian Petrescu ขออภัยนี่เป็นเพียงตัวอย่างหากคุณใช้ DTDs หรือ XSD ให้แน่ใจว่าตรงกับ XML ของคุณ ก่อนที่คุณจะแยกวิเคราะห์ XML จับมันในสตริงและล้อมรอบด้วย '|' และพิมพ์ลงในคอนโซล สิ่งนี้จะบอกคุณว่าคุณกำลังส่งผ่านอักขระพิเศษบางตัวหรือไม่
Romain Hippeau

อ่าฉันเข้าใจแล้ว :) น่าเสียดายที่ฉันลองแล้วและดูเหมือนว่าจะไม่เป็นเช่นนั้นในสถานการณ์นี้ ขอบคุณต่อไป!
Adrian Petrescu

1
ขอบคุณ! สิ่งนี้ช่วยฉันได้เช่นกัน xml.trim (). replaceFirst ("^ ([\\ W] +) <", "<");
stackoverflow

2
ใครบางคนโปรดทำให้คำตอบนี้เป็นที่ยอมรับ แก้ไขปัญหาของฉันได้ทันที ฉันกำลังแยกวิเคราะห์ข้อความที่ขึ้นต้นด้วย "ข้อความ: <? xml เวอร์ชัน .... " ปัญหาคือข้อความก่อนบิต xml ขอบคุณ :)
Ric Jafe

8

ข้อความแสดงข้อผิดพลาดนี้เกิดจากเนื้อหา XML ที่ไม่ถูกต้องในองค์ประกอบเริ่มต้นเสมอ ตัวอย่างเช่นจุดเล็ก ๆ พิเศษ“.” ในส่วนเริ่มต้นขององค์ประกอบ XML

อักขระใด ๆ ก่อน " <?xml…." จะทำให้เกิดข้อผิดพลาด" org.xml.sax.SAXParseException: ไม่อนุญาตให้มีเนื้อหาใน prolog "

จุดเล็ก ๆ ” . ” ก่อนวันที่“<?xml….

ในการแก้ไขให้ลบอักขระแปลก ๆ ทั้งหมดก่อนหน้าไฟล์“<?xml“.

อ้างอิง: http://www.mkyong.com/java/sax-error-content-is-not-allowed-in-prolog/


3
คุณควรพูดถึงที่ที่คุณอ้างถึงว่าmkyong.com/java/sax-error-content-is-not-allowed-in-prolog
arulraj.net

5

ฉันประสบปัญหาเดียวกัน ในกรณีของฉันไฟล์ XML ถูกสร้างขึ้นจากโปรแกรม c # และป้อนลงใน AS400 เพื่อการประมวลผลเพิ่มเติม หลังจากการวิเคราะห์บางส่วนระบุว่าฉันใช้การเข้ารหัส UTF8 ในขณะที่สร้างไฟล์ XML ในขณะที่ javac (ใน AS400) ใช้ "UTF8 ที่ไม่มี 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

5

ฉันมีปัญหาขณะตรวจสอบไฟล์ xml ใน notepad ++ และบันทึกไฟล์แม้ว่าฉันจะมีแท็ก utf-8 xml อันดับต้น ๆ เป็น <?xml version="1.0" encoding="utf-8"?>

ได้รับการแก้ไขโดยการบันทึกไฟล์ใน notpad ++ ด้วยการเข้ารหัส (Tab)> เข้ารหัสใน UTF-8: ถูกเลือก (คือเข้ารหัสใน UTF-8-BOM)



2

ในไฟล์ 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");

ฉันสามารถ deserialize วัตถุได้ดี ดังที่ Romain ได้กล่าวไว้ข้างต้นการเข้ารหัสจำเป็นต้องตรงกัน


1

ฉันประสบปัญหาเดียวกันที่เรียกว่า "ไม่อนุญาตให้ใช้เนื้อหาใน prolog" ในไฟล์ xml ของฉัน

สารละลาย

เริ่มแรกโฟลเดอร์รูทของฉันคือ '# ชื่อไฟล์ '

เมื่อฉันลบอักขระตัวแรก '#' ข้อผิดพลาดได้รับการแก้ไข

ไม่จำเป็นต้องลบ #filename ... ลองทางนี้ ..

แทนที่จะส่งไฟล์หรืออ็อบเจ็กต์ URL ไปยังเมธอด unmarshaller ให้ใช้ FileInputStream

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

1

สาเหตุที่ไม่คาดคิด: #อักขระในเส้นทางไฟล์

เนื่องจากข้อผิดพลาดภายในบางอย่างข้อผิดพลาดไม่อนุญาตให้ใช้เนื้อหาใน prologก็ปรากฏขึ้นหากเนื้อหาของไฟล์นั้นถูกต้อง 100% แต่คุณกำลังให้ชื่อไฟล์เช่นC:\Data\#22\file.xml.

ซึ่งอาจนำไปใช้กับอักขระพิเศษอื่น ๆ ได้เช่นกัน

วิธีตรวจสอบ:หากคุณย้ายไฟล์ไปในเส้นทางที่ไม่มีอักขระพิเศษและข้อผิดพลาดหายไปแสดงว่าเป็นปัญหานี้


1

วันนี้ฉันพบข้อความแสดงข้อผิดพลาดเดียวกัน วิธีแก้ปัญหาคือเปลี่ยนเอกสารจาก UTF-8 พร้อม BOM เป็น UTF-8 โดยไม่มี BOM


ฉันมีปัญหาเดียวกัน การเปลี่ยนรูปแบบไฟล์ช่วยแก้ปัญหาได้ ขอบคุณ!
code_fish

0

ฉันมีอักขระแท็บแทนช่องว่าง การเปลี่ยนแท็บ '\ t' ช่วยแก้ปัญหาได้

ตัดและวางเอกสารทั้งหมดลงในโปรแกรมแก้ไขเช่น Notepad ++ และแสดงอักขระทั้งหมด


0

ในตัวอย่างปัญหาของฉันวิธีแก้ปัญหาคือแทนที่ umlauts (äöü) ภาษาเยอรมันด้วย HTML-equivalent ...


0

การร้องเป็นสาเหตุข้างต้น“ org.xml.sax.SAXParseException: ไม่อนุญาตให้มีเนื้อหาในข้อยกเว้นของ 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: hello<?xml version='1.0' encoding='utf-16'?>

0

ด้วยจิตวิญญาณของ "เพียงแค่ลบอักขระแปลก ๆ ทั้งหมดก่อน <? xml" นี่คือรหัส 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.