„Treść nie jest dozwolona w prologu” podczas analizowania doskonale poprawnego XML w GAE


109

Przez ostatnie 48 godzin waliłem głową w ten absolutnie irytujący błąd, więc pomyślałem, że w końcu rzucę ręcznik i spróbuję zapytać tutaj, zanim wyrzucę laptopa przez okno.

Próbuję przeanalizować XML odpowiedzi z połączenia, które wykonałem do AWS SimpleDB. Odpowiedź wraca na drut w porządku; na przykład może wyglądać tak:

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

Przekazuję ten XML do parsera z

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

i dzwonię eventReader.nextEvent();kilka razy, aby uzyskać potrzebne dane.

Oto dziwna część - działa świetnie na lokalnym serwerze. Nadchodzi odpowiedź, analizuję ją, wszyscy są szczęśliwi. Problem polega na tym, że kiedy wdrażam kod w Google App Engine, żądanie wychodzące nadal działa, a XML odpowiedzi wydaje mi się w 100% identyczny i poprawny, ale odpowiedź nie jest analizowana z następującym wyjątkiem:

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)

Podwójnie, potrójnie, poczwórnie sprawdziłem ten XML pod kątem „niewidocznych znaków” lub znaków zakodowanych w formacie innym niż UTF8 itp. Spojrzałem na to bajt po bajcie w tablicy pod kątem znaków kolejności bajtów lub czegoś w tym rodzaju. Nic; przechodzi wszystkie testy walidacyjne, jakie mogłem mu rzucić. Co dziwniejsze, dzieje się tak, gdy używam również parsera opartego na Saksonii - ale TYLKO w GAE, zawsze działa dobrze w moim lokalnym środowisku.

Utrudnia to śledzenie kodu pod kątem problemów, gdy mogę uruchomić debugger tylko w środowisku, które działa idealnie (nie znalazłem żadnego dobrego sposobu na zdalne debugowanie w GAE). Niemniej jednak, używając prymitywnych środków, które posiadam, wypróbowałem milion podejść, w tym:

  • XML z prologiem i bez niego
  • Z nowymi liniami i bez
  • Z atrybutem „encoding =” w prologu i bez niego
  • Oba style nowej linii
  • Z i bez informacji o porcjowaniu obecnych w strumieniu HTTP

Wypróbowałem większość z nich w wielu kombinacjach, w których miało sens, aby wchodziły w interakcje - nic! Jestem na końcu mojego dowcipu. Czy ktoś widział wcześniej taki problem, który, miejmy nadzieję, może rzucić na to trochę światła?

Dzięki!


Prawdopodobnie będziemy musieli zobaczyć więcej kodu. Inną możliwością jest to, że lokalnie nie jest on dzielony na kawałki, gdy jest na GAE. Jak postępujesz z kodem przed przekazaniem go do parsera?
Romain Hippeau

Rozważyłem również możliwość fragmentacji, ale wydaje się, że tak nie jest, ponieważ komunikat o błędzie, który wyrzuca parser, zawiera cały kod XML (jest wklejony powyżej). Cały zmodyfikowany kod SDK można znaleźć na github.com/AdrianP/aws-sdk-for-java (spójrz na najnowsze commity), ale jest tam DUŻO kodu. Postaram się wkrótce stworzyć mniejszą powtarzalną próbkę, chociaż nawet to będzie trudne. To bardzo skomplikowany program ... Jednak dzięki za Twoją opinię! :)
Adrian Petrescu


@Raedwald, nie wydaje mi się, że to moje pytanie jest duplikatem, ponieważ moje pytanie zostało opublikowane rok wcześniej niż to jedno :)
Adrian Petrescu

1
To powinien być przykład tego, jak należy zadać pytanie na SO, przeczytanie go dało mi różne informacje na temat debugowania jako programista (dzięki OP)
Sudip Bhandari

Odpowiedzi:


129

Kodowanie w Twoim XML i XSD (lub DTD) jest różne.
Nagłówek pliku XML: <?xml version='1.0' encoding='utf-8'?>
nagłówek pliku XSD:<?xml version='1.0' encoding='utf-16'?>

Innym możliwym scenariuszem, który powoduje to, jest sytuacja, gdy cokolwiek występuje przed deklaracją typu dokumentu XML. tj. możesz mieć coś takiego w buforze:

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

lub nawet spacja lub znak specjalny.

Istnieje kilka znaków specjalnych zwanych znacznikami kolejności bajtów, które mogą znajdować się w buforze. Przed przekazaniem bufora do Parsera zrób to ...

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

Cześć Romain, dzięki za odpowiedź! Wiele razy sprawdzałem coś w buforze przed prologiem (w tym ukryte znaki), ale po prostu nie ma tam nic więcej. Spróbuję jednak przejść na kodowanie utf-16 - z ciekawości, skąd masz informacje, że XSD używa UTF-16?
Adrian Petrescu

@Adrian Petrescu Przepraszamy, to są tylko przykłady. Jeśli używasz DTD lub XSD, upewnij się, że pasują do Twojego XML. Zanim przeanalizujesz XML, przechwyć go w łańcuchu i otocz znakiem „|” i wydrukuj go na konsoli. Dzięki temu dowiesz się, czy przekazujesz dodatkowe znaki.
Romain Hippeau

Ach, widzę :) Niestety próbowałem i nie wydaje się, żeby tak było w tej sytuacji. W każdym razie dzięki!
Adrian Petrescu

1
Dzięki! To też mnie uratowało. xml.trim (). replaceFirst ("^ ([\\ W] +) <", "<");
stackoverflow

2
Niech ktoś uzna tę odpowiedź za zaakceptowaną. Od razu rozwiązałem mój problem. Analizowałem wiadomość, która zaczynała się od „Wiadomość: <? Wersja xml ....”. Problem dotyczył tekstu przed bitem XML. Dzięki :)
Ric Jafe

8

Ten komunikat o błędzie jest zawsze spowodowany nieprawidłową treścią XML w elemencie początkowym. Na przykład bardzo mała kropka „.” na początku elementu XML.

Wszelkie znaki przed „ <?xml….” spowodują powyższy komunikat o błędzieorg.xml.sax.SAXParseException: Content is not allowed in prolog ”.

Mała kropka ” . " zanim“<?xml….

Aby to naprawić, po prostu usuń wszystkie te dziwne znaki przed rozszerzeniem “<?xml“.

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


3
Powinieneś wspomnieć, gdzie odesłałeś,
arulraj.net

5

Miałem ten sam problem. W moim przypadku pliki XML zostały wygenerowane z programu C # i przesłane do AS400 w celu dalszego przetwarzania. Po przeprowadzeniu analizy stwierdziłem, że podczas generowania plików XML używam kodowania UTF8, podczas gdy javac (w AS400) używa „UTF8 bez BOM”. Musiałem więc napisać dodatkowy kod podobny do wymienionego poniżej:

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

Miałem problem podczas sprawdzania pliku xml w notatniku ++ i zapisywania pliku, chociaż miałem górny znacznik xml utf-8 jako <?xml version="1.0" encoding="utf-8"?>

Naprawiono, zapisując plik w notpad ++ z Kodowaniem (Tab)> Koduj w UTF-8: zaznaczono (było Kodowanie w UTF-8-BOM)


3

Usunięcie deklaracji xml rozwiązało problem

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

2

W moim pliku xml nagłówek wyglądał następująco:

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

W pliku testowym odczytywałem bajty pliku i dekodowałem dane jako UTF-8 (nie zdając sobie sprawy, że nagłówek w tym pliku to utf-16), aby utworzyć ciąg.

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

Kiedy próbowałem deserializować ten ciąg na obiekt, widziałem ten sam błąd:

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

Kiedy zaktualizowałem drugą linię do

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

Udało mi się zdeserializować obiekt w porządku. Jak więc Romain zauważył powyżej, kodowanie musi pasować.


1

Napotkałem ten sam problem o nazwie „Treść nie jest dozwolona w prologu” w moim pliku xml.

Rozwiązanie

Początkowo moim folderem głównym był „# Filename ”.

Kiedy usunąłem pierwszy znak „#”, błąd został rozwiązany.

Nie ma potrzeby usuwania #filename ... Spróbuj w ten sposób ...

Zamiast przekazywać obiekt File lub URL do metody unmarshaller, użyj FileInputStream.

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

1

Nieoczekiwany powód: #znak w ścieżce pliku

Z powodu jakiegoś wewnętrznego błędu, błąd Treść nie jest dozwolona w prologu pojawia się również, jeśli sama zawartość pliku jest w 100% poprawna, ale podajesz nazwę pliku, taką jak C:\Data\#22\file.xml.

Może to również dotyczyć innych znaków specjalnych.

Jak sprawdzić: Jeśli przeniesiesz plik do ścieżki bez znaków specjalnych i błąd zniknie, to był to problem.


1

Wyłapałem dziś ten sam komunikat o błędzie. Rozwiązaniem była zmiana dokumentu z UTF-8 z BOM na UTF-8 bez BOM


Miałem ten sam problem. Zmiana formatu pliku rozwiązała problem. Dzięki!
code_fish

0

Zamiast spacji miałem znak tabulacji. Zastąpienie zakładki „\ t” rozwiązało problem.

Wytnij i wklej cały dokument do edytora, takiego jak Notepad ++, i wyświetl wszystkie znaki.


0

W moim przypadku rozwiązaniem było zastąpienie niemieckich umlautów (äöü) ich odpowiednikami HTML ...


0

poniżej są przyczyną powyżej wyjątku „org.xml.sax.SAXParseException: Content is not allowed in prolog”.

  1. Najpierw sprawdź ścieżkę do plików schema.xsd i file.xml.
  2. Kodowanie w XML i XSD (lub DTD) powinno być takie samo.
    Nagłówek pliku XML: <?xml version='1.0' encoding='utf-8'?>
    nagłówek pliku XSD:<?xml version='1.0' encoding='utf-8'?>
  3. jeśli cokolwiek nastąpi przed deklaracją typu dokumentu XML.ie: hello<?xml version='1.0' encoding='utf-16'?>

0

W duchu „po prostu usuń wszystkie te dziwne znaki przed <? Xml”, oto mój kod Java, który działa dobrze w przypadku wprowadzania danych przez 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, bajty, które widziałem to (dziesiętnie): 239, 187, 191.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.