“Conteúdo não é permitido no prólogo” ao analisar XML perfeitamente válido no GAE

109

Tenho batido minha cabeça contra esse bug absolutamente irritante nas últimas 48 horas, então pensei em finalmente jogar a toalha e tentar perguntar aqui antes de jogar meu laptop pela janela.

Estou tentando analisar o XML de resposta de uma chamada que fiz para AWS SimpleDB. A resposta está voltando muito bem; por exemplo, pode ser parecido com:

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

Eu passo este XML para um analisador com

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

e ligar eventReader.nextEvent();várias vezes para obter os dados que desejo.

Aqui está a parte bizarra - funciona muito bem dentro do servidor local. A resposta chega, eu analiso, todos estão felizes. O problema é que, quando implanto o código no Google App Engine, a solicitação de saída ainda funciona e o XML de resposta parece 100% idêntico e correto para mim, mas a resposta falha ao analisar com a seguinte exceção:

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)

Eu verifiquei duplo, triplo, quádruplo neste XML para 'caracteres invisíveis' ou caracteres não codificados em UTF8, etc. Eu olhei para ele byte a byte em uma matriz para marcas de ordem de byte ou algo dessa natureza. Nada; ele passa em todos os testes de validação que eu poderia lançar nele. Ainda mais estranho, isso acontece se eu usar um analisador baseado em saxão também - mas SOMENTE no GAE, ele sempre funciona bem no meu ambiente local.

Isso torna muito difícil rastrear o código para problemas quando eu só posso executar o depurador em um ambiente que funciona perfeitamente (não encontrei nenhuma boa maneira de depurar remotamente no GAE). No entanto, usando os meios primitivos que tenho, tentei um milhão de abordagens, incluindo:

  • XML com e sem prólogo
  • Com e sem novas linhas
  • Com e sem o atributo "encoding =" no prólogo
  • Ambos os estilos de nova linha
  • Com e sem as informações de chunking presentes no fluxo HTTP

E eu tentei a maioria deles em várias combinações onde fazia sentido que eles interagissem - nada! Estou perdendo o juízo. Alguém já viu um problema como este antes que possa lançar alguma luz sobre ele?

Obrigado!

Adrian Petrescu
fonte
Provavelmente precisaremos ver mais alguns códigos. Outra possibilidade é que localmente ele não seja fragmentado enquanto está no GAE. Como você está lidando com o código antes de passá-lo para o analisador?
Romain Hippeau
Eu considerei a possibilidade de fragmentação também, mas não parece ser o caso, pois a mensagem de erro que o analisador está emitindo contém todo o XML ali (está colado acima). Todo o código SDK modificado pode ser encontrado em github.com/AdrianP/aws-sdk-for-java (veja os commits mais recentes), mas há MUITO código lá. Tentarei criar uma amostra reproduzível menor em breve, embora até isso seja difícil. É um software muito complicado ... Obrigado por seus comentários! :)
Adrian Petrescu
@Raedwald, não acho que seja a minha pergunta duplicada, já que minha pergunta foi postada um ano antes daquela aqui :)
Adrian Petrescu
1
Este deve ser um exemplo de como uma pergunta deve ser feita no SO. A leitura me deu vários insights sobre como depurar como um desenvolvedor (obrigado OP)
Sudip Bhandari

Respostas:

129

A codificação em seu XML e XSD (ou DTD) são diferentes.
Cabeçalho do arquivo XML: <?xml version='1.0' encoding='utf-8'?>
cabeçalho do arquivo XSD:<?xml version='1.0' encoding='utf-16'?>

Outro cenário possível que causa isso é quando algo vem antes da declaração do tipo de documento XML. ou seja, você pode ter algo assim no buffer:

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

ou mesmo um espaço ou personagem especial.

Existem alguns caracteres especiais chamados marcadores de ordem de bytes que podem estar no buffer. Antes de passar o buffer para o analisador, faça isso ...

String xml = "<?xml ...";
xml = xml.trim().replaceFirst("^([\\W]+)<","<");
Romain Hippeau
fonte
Oi Romain, obrigado pela resposta! Eu verifiquei duas ou três vezes muitas vezes por qualquer coisa no buffer antes do prólogo (incluindo caracteres ocultos), mas simplesmente não há mais nada lá. Vou tentar mudar para a codificação utf-16, no entanto - por curiosidade, de onde você obteve a informação de que o XSD usa UTF-16?
Adrian Petrescu
@Adrian Petrescu Desculpe, estes são apenas exemplos. Se você estiver usando DTDs ou XSDs, certifique-se de que eles correspondem ao seu XML. Antes de analisar o XML, capture-o em uma String e coloque-o entre '|' e imprima no console. Isso dirá se você está passando alguns caracteres extras.
Romain Hippeau
Ah, entendo :) Infelizmente tentei e não parece ser o caso nesta situação. Obrigado mesmo assim!
Adrian Petrescu
1
Obrigado! Isso também me salvou. xml.trim (). replaceFirst ("^ ([\\ W] +) <", "<");
stackoverflow de
2
Alguém, por favor, torne esta a resposta aceita. Resolvi meu problema imediatamente. Eu estava analisando uma mensagem que começava com "Mensagem: <? Versão xml ...." O problema era o texto antes do bit xml. Obrigado :)
Ric Jafe
8

Essa mensagem de erro é sempre causada pelo conteúdo XML inválido no elemento inicial. Por exemplo, um ponto extra pequeno “.” no início do elemento XML.

Qualquer caractere antes de “ <?xml….” causará a mensagem de erro “ org.xml.sax.SAXParseException: Conteúdo não permitido no prólogo ”.

Um pequeno ponto “ . " antes de o“<?xml….

Para consertar, basta deletar todos aqueles personagens estranhos antes do “<?xml“.

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

Sunmit Girme
fonte
3
Você deve mencionar para onde fez referência que mkyong.com/java/sax-error-content-is-not-allowed-in-prolog
arulraj.net
5

Eu estava enfrentando o mesmo problema. No meu caso, os arquivos XML foram gerados a partir do programa c # e alimentados no AS400 para processamento posterior. Após algumas análises, identifiquei que estava usando a codificação UTF8 ao gerar arquivos XML, enquanto o javac (no AS400) usa "UTF8 sem BOM". Então, tive que escrever um código extra semelhante ao mencionado abaixo:

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

Tive problemas ao inspecionar o arquivo xml no notepad ++ e salvar o arquivo, embora eu tivesse a tag xml utf-8 principal como <?xml version="1.0" encoding="utf-8"?>

Foi corrigido salvando o arquivo no notpad ++ com Codificação (Guia)> Codificar em UTF-8: selecionado (era Codificar em UTF-8-BOM)

techloris_109
fonte
3

Remover a declaração xml resolveu

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

No meu arquivo xml, o cabeçalho era assim:

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

Em um arquivo de teste, eu estava lendo os bytes do arquivo e decodificando os dados como UTF-8 (não percebendo que o cabeçalho neste arquivo era utf-16) para criar uma string.

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

Quando tentei desserializar esta string em um objeto, estava vendo o mesmo erro:

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

Quando atualizei a segunda linha para

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

Consegui desserializar o objeto perfeitamente. Como Romain observou acima, as codificações precisam ser correspondentes.

dfritch
fonte
1

Eu estava enfrentando o mesmo problema chamado "Conteúdo não permitido no prólogo" no meu arquivo xml.

Solução

Inicialmente, minha pasta raiz era '# Filename '.

Quando removi o primeiro caractere '#', o erro foi resolvido.

Não há necessidade de remover o #filename ... Tente desta forma ..

Em vez de passar um objeto File ou URL para o método unmarshaller, use um FileInputStream.

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

Motivo inesperado: #caractere no caminho do arquivo

Devido a algum bug interno, o erro Conteúdo não permitido no prólogo também aparece se o conteúdo do arquivo em si estiver 100% correto, mas você está fornecendo o nome do arquivo comoC:\Data\#22\file.xml .

Isso pode se aplicar a outros caracteres especiais também.

Como verificar: se você mover o arquivo para um caminho sem caracteres especiais e o erro desaparecer, esse é o problema.

miroxlav
fonte
1

Recebi a mesma mensagem de erro hoje. A solução foi mudar o documento de UTF-8 com BOM para UTF-8 sem BOM

matjung
fonte
Eu tive o mesmo problema. Alterar o formato do arquivo resolveu o problema. Obrigado!
code_fish
0

Eu tinha um caractere de tabulação em vez de espaços. Substituir a guia '\ t' corrigiu o problema.

Recorte e cole todo o documento em um editor como o Notepad ++ e exiba todos os caracteres.

SoloPilot
fonte
0

No meu caso do problema, a solução foi substituir tremas alemães (äöü) por seus equivalentes em HTML ...

MBaas
fonte
0

abaixo estão as causas acima “org.xml.sax.SAXParseException: Conteúdo não permitido no prólogo” exceção.

  1. Primeiro verifique o caminho do arquivo de schema.xsd e file.xml.
  2. A codificação em seu XML e XSD (ou DTD) deve ser a mesma.
    Cabeçalho do arquivo XML: <?xml version='1.0' encoding='utf-8'?>
    cabeçalho do arquivo XSD:<?xml version='1.0' encoding='utf-8'?>
  3. se algo vier antes da declaração do tipo de documento XML. por exemplo: hello<?xml version='1.0' encoding='utf-16'?>
Avinash Dubey
fonte
0

No espírito de "apenas excluir todos aqueles caracteres estranhos antes do <? Xml", aqui está meu código Java, que funciona bem com entrada por meio de um 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, os bytes que eu estava vendo são (em decimal): 239, 187, 191.

Tamias
fonte