GAEで完全に有効なXMLを解析するときの「コンテンツはプロローグで許可されていません」


109

私は過去48時間、この非常に腹立たしいバグに頭を殴っていたので、ラップトップを窓から投げ出す前に、ようやくタオルを投げ入れて、ここで聞いてみようと思いました。

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
  • 改行ありとなし
  • プロローグの "encoding ="属性の有無
  • 両方の改行スタイル
  • HTTPストリームに存在するチャンキング情報の有無にかかわらず

そして、私はこれらのほとんどを、それらが相互作用することが理にかなっている複数の組み合わせで試しました-何も!私は私の機知の終わりにいます。誰かがこの問題を以前に見たことがありますか?

ありがとう!


おそらく、もう少しコードを見る必要があるでしょう。別の可能性としては、GAEではローカルにチャンクされていない可能性があります。パーサーに渡す前に、コードをどのように処理していますか?
Romain Hippeau

チャンクの可能性も検討しましたが、パーサーがスローしているというエラーメッセージには、XML全体が含まれている(上に貼り付けています)ため、そうではないようです。変更されたSDKコード全体はgithub.com/AdrianP/aws-sdk-for-java(最新のコミットを確認)にありますが、そこにはたくさんのコードがあります。私はすぐに、より小さな再現可能なサンプルを作成することを試みますが、それも難しいでしょう。とても複雑なソフトウェアです...フィードバックありがとうございます!:)
Adrian Petrescu


@Raedwald、私の質問はそれよりも1年前に投稿されたので、重複しているのは私の質問だとは思いません:)
Adrian Petrescu 14

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

これを引き起こすもう1つの考えられるシナリオは、XML文書型宣言の前に何かが来る場合です。つまり、バッファに次のようなものがあるかもしれません:

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

またはスペースや特殊文字。

バッファにある可能性のあるバイトオーダーマーカーと呼ばれるいくつかの特殊文字があります。バッファをパーサーに渡す前に、これを行ってください...

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

こんにちはロメイン、応答をありがとう!私はプロローグの前に(隠し文字を含む)バッファー内の何かを何度もダブルおよびトリプルチェックしましたが、そこには他に何もありません。ただし、utf-16エンコーディングへの切り替えを試してみましょう-不思議なことに、XSDがUTF-16を使用しているという情報はどこで得ましたか?
エイドリアンPetrescu

@Adrian Petrescu申し訳ありませんが、これらは単なる例です。DTDまたはXSDを使用している場合は、XMLと一致していることを確認してください。XMLを解析する前に、それを文字列に取り込み、 '|'で囲みます。それをコンソールに出力します。これにより、追加の文字を渡すかどうかがわかります。
Romain Hippeau

ああ、そうですね:)残念ながら試してみましたが、この状況ではそうではありません。とにかくありがとう!
エイドリアンPetrescu

1
ありがとう!これも私を救った。xml.trim()。replaceFirst( "^([\\ W] +)<"、 "<");
stackoverflow 2013年

2
誰かがこれを受け入れられた答えにしてください。私の問題をすぐに解決しました。「Message:<?xml version ....」で始まるメッセージを解析していましたが、問題はxmlビットの前のテキストでした。ありがとう:)
Ric Jafe 2013

8

このエラーメッセージは常に、開始要素の無効なXMLコンテンツが原因で発生します。たとえば、余分な小さなドット「。」XML要素の先頭。

<?xml….」の前に文字があると、上記の「org.xml.sax.SAXParseException:Content is not allowed in prolog」エラーメッセージが表示されます。

小さな点“ " の前に“<?xml….

修正するには、の前にある奇妙な文字をすべて削除してください“<?xml“

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



5

私は同じ問題に直面していました。私の場合、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

Notepad ++でxmlファイルを検査してファイルを保存するときに問題が発生しましたが、一番上のutf-8 xmlタグは <?xml version="1.0" encoding="utf-8"?>

Enpad(Tab)> Encode in UTF-8:selected(notcode in UTF-8-BOM)を使用してnotpad ++でファイルを保存することで修正されました


3

xml宣言を削除すると解決しました

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

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.

2行目を更新したとき

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

オブジェクトを正常に逆シリアル化することができました。したがって、Romainが前述したように、エンコーディングは一致する必要があります。


1

私のxmlファイルで「コンテンツはプロローグで許可されていません」と呼ばれる同じ問題に直面していました。

解決

最初、私のルートフォルダーは ' #Filename 'でした。

最初の文字「#」を削除すると、エラーが解決しました。

#filenameを削除する必要はありません...このようにしてください。

unmarshallerメソッドにFileまたはURLオブジェクトを渡す代わりに、FileInputStreamを使用します。

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

1

予期しない理由:#ファイルパス内の文字

いくつかの内部バグにより、ファイルのコンテンツ自体が100%正しいが、次のようにファイル名を指定している場合にも、エラー「コンテンツはプロローグで許可されていません」が表示されます。C:\Data\#22\file.xml

これは他の特殊文字にも適用される可能性があります。

確認方法:ファイルを特殊文字のないパスに移動し、エラーが消えた場合は、この問題が原因です。


1

今日も同じエラーメッセージを受け取りました。解決策は、ドキュメントをBOM付きのUTF-8からBOMなしのUTF-8に変更することでした。


同じ問題がありました。ファイル形式を変更すると問題が解決しました。ありがとう!
code_fish

0

スペースの代わりにタブ文字がありました。タブ「\ t」を置き換えると問題が修正されました。

ドキュメント全体を切り取ってNotepad ++などのエディタに貼り付け、すべての文字を表示します。


0

問題の私の例では、解決策はドイツ語のウムラウト(äöü)をHTMLの同等のものに置き換えることでした...


0

以下は、「org.xml.sax.SAXParseException:コンテンツはプロローグで許可されていない」という例外の原因です。

  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、私が見たバイトは(10進数で)239、187、191です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.