"Inhalt ist in Prolog nicht zulässig", wenn perfekt gültiges XML auf GAE analysiert wird

109

Ich habe in den letzten 48 Stunden meinen Kopf gegen diesen absolut wütenden Käfer geschlagen, also dachte ich, ich würde endlich das Handtuch werfen und versuchen, hier zu fragen, bevor ich meinen Laptop aus dem Fenster schmeiße.

Ich versuche, die Antwort-XML von einem Aufruf an AWS SimpleDB zu analysieren. Die Antwort kommt ganz gut auf den Draht zurück; Zum Beispiel könnte es so aussehen:

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

Ich übergebe dieses XML an einen Parser mit

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

und rufe eventReader.nextEvent();ein paar Mal an, um die gewünschten Daten zu erhalten.

Hier ist der bizarre Teil - er funktioniert hervorragend auf dem lokalen Server. Die Antwort kommt herein, ich analysiere sie, alle sind glücklich. Das Problem ist, dass beim Bereitstellen des Codes in Google App Engine die ausgehende Anforderung weiterhin funktioniert und die Antwort-XML für mich zu 100% identisch und korrekt erscheint, die Antwort jedoch mit der folgenden Ausnahme nicht analysiert werden kann:

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)

Ich habe dieses XML doppelt, dreifach, vierfach auf "unsichtbare Zeichen" oder nicht UTF8-codierte Zeichen usw. überprüft. Ich habe es Byte für Byte in einem Array auf Bytereihenfolge-Markierungen oder ähnliches untersucht. Nichts; Es besteht jeden Validierungstest, den ich durchführen könnte. Noch seltsamer ist es, wenn ich auch einen sächsischen Parser verwende - aber NUR auf GAE funktioniert es in meiner lokalen Umgebung immer einwandfrei.

Es macht es sehr schwierig, den Code auf Probleme zu verfolgen, wenn ich den Debugger nur in einer Umgebung ausführen kann, die perfekt funktioniert (ich habe keine gute Möglichkeit gefunden, auf GAE remote zu debuggen). Trotzdem habe ich mit den primitiven Mitteln, die ich habe, eine Million Ansätze ausprobiert, darunter:

  • XML mit und ohne Prolog
  • Mit und ohne Zeilenumbruch
  • Mit und ohne das Attribut "encoding =" im Prolog
  • Beide Newline-Stile
  • Mit und ohne die im HTTP-Stream vorhandenen Chunking-Informationen

Und ich habe die meisten davon in mehreren Kombinationen ausprobiert, bei denen es Sinn machte, dass sie interagieren würden - nichts! Ich bin mit meinem Latein am Ende. Hat jemand schon einmal ein Problem wie dieses gesehen, das hoffentlich etwas Licht ins Dunkel bringen kann?

Vielen Dank!

Adrian Petrescu
quelle
Wir werden wahrscheinlich mehr Code sehen müssen. Eine andere Möglichkeit ist, dass es lokal nicht beschädigt wird, während es auf GAE ist. Wie gehen Sie mit dem Code um, bevor Sie ihn an den Parser übergeben?
Romain Hippeau
Ich habe auch die Chunking-Möglichkeit in Betracht gezogen, aber es scheint nicht der Fall zu sein, da die Fehlermeldung, die der Parser auslöst, das gesamte XML genau dort enthält (es wurde oben eingefügt). Der gesamte modifizierte SDK-Code ist unter github.com/AdrianP/aws-sdk-for-java zu finden (siehe die neuesten Commits), aber es gibt dort eine Menge Code. Ich werde versuchen, bald ein kleineres reproduzierbares Muster zu erstellen, obwohl selbst das schwierig sein wird. Es ist eine große, komplizierte Software ... Vielen Dank für Ihr Feedback! :)
Adrian Petrescu
@ Raedwald, ich glaube nicht, dass es meine Frage ist, die das Duplikat ist, da meine Frage ein Jahr früher als diese gestellt wurde :)
Adrian Petrescu
1
Dies sollte ein Beispiel dafür sein, wie eine Frage zu SO gestellt werden sollte. Das Lesen gab mir verschiedene Einblicke in das Debuggen als Entwickler (danke OP)
Sudip Bhandari

Antworten:

129

Die Codierung in XML und XSD (oder DTD) ist unterschiedlich.
XML-Dateikopf: <?xml version='1.0' encoding='utf-8'?>
XSD-Dateikopf:<?xml version='1.0' encoding='utf-16'?>

Ein weiteres mögliches Szenario, das dies verursacht, ist, wenn etwas vor der XML-Dokumenttypdeklaration steht. Das heißt, Sie haben möglicherweise so etwas im Puffer:

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

oder sogar ein Leerzeichen oder ein Sonderzeichen.

Es gibt einige Sonderzeichen, die als Byte-Ordnungsmarkierungen bezeichnet werden und sich im Puffer befinden könnten. Bevor Sie den Puffer an den Parser übergeben, gehen Sie wie folgt vor ...

String xml = "<?xml ...";
xml = xml.trim().replaceFirst("^([\\W]+)<","<");
Romain Hippeau
quelle
Hallo Romain, danke für die Antwort! Ich habe vor dem Prolog viele Male doppelt und dreifach nach etwas im Puffer gesucht (einschließlich versteckter Zeichen), aber es gibt einfach nichts anderes. Ich werde jedoch versuchen, auf die utf-16-Codierung umzusteigen - aus Neugier, woher haben Sie die Informationen, dass die XSD UTF-16 verwendet?
Adrian Petrescu
@Adrian Petrescu Entschuldigung, dies sind nur Beispiele. Wenn Sie DTDs oder XSDs verwenden, stellen Sie sicher, dass sie mit Ihrem XML übereinstimmen. Bevor Sie das XML analysieren, erfassen Sie es in einem String und umgeben Sie es mit '|' und drucken Sie es auf der Konsole. Hier erfahren Sie, ob Sie zusätzliche Zeichen eingeben.
Romain Hippeau
Ah, ich verstehe :) Leider habe ich es versucht und es scheint in dieser Situation nicht der Fall zu sein. Danke trotzdem!
Adrian Petrescu
1
Vielen Dank! Das hat mich auch gerettet. xml.trim (). replaceFirst ("^ ([\\ W] +) <", "<");
Stackoverflow
2
Jemand, bitte machen Sie dies zur akzeptierten Antwort. Ich habe mein Problem sofort gelöst. Ich habe eine Nachricht analysiert, die mit "Nachricht: <? XML-Version ...." begann. Das Problem war der Text vor dem XML-Bit. Danke :)
Ric Jafe
8

Diese Fehlermeldung wird immer durch den ungültigen XML-Inhalt im Anfangselement verursacht. Zum Beispiel ein extra kleiner Punkt "." am Anfang des XML-Elements.

Alle Zeichen vor dem " <?xml…." verursachen die Fehlermeldung " org.xml.sax.SAXParseException: Inhalt ist im Prolog nicht zulässig ".

Ein kleiner Punkt “ . " Vor dem“<?xml….

Um dies zu beheben, löschen Sie einfach alle diese seltsamen Zeichen vor dem “<?xml“.

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

Sunmit Girme
quelle
3
Sie sollten erwähnen, wo Sie darauf verwiesen haben, dass mkyong.com/java/sax-error-content-is-not-allowed-in-prolog
arulraj.net
5

Ich stand vor dem gleichen Problem. In meinem Fall wurden XML-Dateien aus dem c # -Programm generiert und zur weiteren Verarbeitung in AS400 eingespeist. Nach einigen Analysen wurde festgestellt, dass ich beim Generieren von XML-Dateien die UTF8-Codierung verwendet habe, während javac (in AS400) "UTF8 ohne Stückliste" verwendet. Also musste ich zusätzlichen Code schreiben, ähnlich wie unten erwähnt:

//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
Saturn CAU
quelle
5

Ich hatte ein Problem beim Überprüfen der XML-Datei in Notepad ++ und beim Speichern der Datei, obwohl ich das oberste utf-8-XML-Tag als hatte <?xml version="1.0" encoding="utf-8"?>

Wurde behoben, indem die Datei in notpad ++ mit Codierung (Tab)> In UTF-8 codieren gespeichert wurde: ausgewählt (war in UTF-8-Stückliste codieren)

techloris_109
quelle
3

Das Entfernen der XML-Deklaration hat das Problem behoben

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

In meiner XML-Datei sah der Header folgendermaßen aus:

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

In einer Testdatei habe ich die Dateibytes gelesen und die Daten als UTF-8 dekodiert (nicht erkannt, dass der Header in dieser Datei utf-16 war), um eine Zeichenfolge zu erstellen.

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

Als ich versuchte, diese Zeichenfolge in ein Objekt zu deserialisieren, wurde der gleiche Fehler angezeigt:

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

Als ich die zweite Zeile auf aktualisiert habe

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

Ich konnte das Objekt gut deserialisieren. Wie Romain oben bemerkt hatte, müssen die Codierungen übereinstimmen.

dfritch
quelle
1

Ich hatte das gleiche Problem mit dem Namen "Inhalt ist in Prolog nicht zulässig" in meiner XML-Datei.

Lösung

Anfangs war mein Stammordner '# Dateiname '.

Als ich das erste Zeichen '#' entfernte, wurde der Fehler behoben.

Der #Dateiname muss nicht entfernt werden ... Versuchen Sie es auf diese Weise ..

Verwenden Sie einen FileInputStream, anstatt ein Datei- oder URL-Objekt an die Unmarshaller-Methode zu übergeben.

File myFile = new File("........");
Object obj = unmarshaller.unmarshal(new FileInputStream(myFile));
Ravi Kiran
quelle
1

Unerwarteter Grund: #Zeichen im Dateipfad

Aufgrund eines internen Fehlers ist der Fehler Inhalt im Prolog nicht zulässig angezeigt. auch angezeigt, wenn der Dateiinhalt selbst zu 100% korrekt ist, Sie jedoch den Dateinamen wie angeben C:\Data\#22\file.xml.

Dies gilt möglicherweise auch für andere Sonderzeichen.

So überprüfen Sie: Wenn Sie Ihre Datei in einen Pfad ohne Sonderzeichen verschieben und der Fehler verschwindet, liegt dieses Problem vor.

miroxlav
quelle
1

Ich habe heute die gleiche Fehlermeldung erhalten. Die Lösung bestand darin, das Dokument von UTF-8 mit Stückliste in UTF-8 ohne Stückliste zu ändern

Matjung
quelle
Ich hatte das gleiche Problem. Durch Ändern des Dateiformats wurde das Problem behoben. Vielen Dank!
code_fish
0

Ich hatte ein Tabulatorzeichen anstelle von Leerzeichen. Das Ersetzen der Registerkarte '\ t' hat das Problem behoben.

Schneiden Sie das gesamte Dokument aus und fügen Sie es in einen Editor wie Notepad ++ ein und zeigen Sie alle Zeichen an.

SoloPilot
quelle
0

In meinem Fall bestand die Lösung darin, deutsche Umlaute (äöü) durch ihre HTML-Äquivalente zu ersetzen ...

MBaas
quelle
0

Die folgenden Ursachen liegen über der Ausnahme "org.xml.sax.SAXParseException: Inhalt ist im Prolog nicht zulässig".

  1. Überprüfen Sie zuerst den Dateipfad von schema.xsd und file.xml.
  2. Die Codierung in XML und XSD (oder DTD) sollte identisch sein.
    XML-Dateikopf: <?xml version='1.0' encoding='utf-8'?>
    XSD-Dateikopf:<?xml version='1.0' encoding='utf-8'?>
  3. Wenn etwas vor der XML-Dokumenttypdeklaration steht.ie: hello<?xml version='1.0' encoding='utf-16'?>
Avinash Dubey
quelle
0

Im Sinne von "Lösche einfach alle diese seltsamen Zeichen vor der <? Xml" ist hier mein Java-Code, der gut mit der Eingabe über einen BufferedReader funktioniert:

    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, die Bytes, die ich gesehen habe, sind (dezimal): 239, 187, 191.

Tamias
quelle