"No se permite contenido en el prólogo" al analizar XML perfectamente válido en GAE

109

Me he estado golpeando la cabeza contra este error absolutamente exasperante durante las últimas 48 horas, así que pensé que finalmente arrojaría la toalla e intentaría preguntar aquí antes de tirar mi computadora portátil por la ventana.

Estoy tratando de analizar el XML de respuesta de una llamada que hice a AWS SimpleDB. La respuesta está regresando muy bien por el cable; por ejemplo, puede verse así:

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

Paso este XML a un analizador con

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

y llamo eventReader.nextEvent();varias veces para obtener los datos que quiero.

Aquí está la parte extraña: funciona muy bien dentro del servidor local. La respuesta llega, la analizo, todos están felices. El problema es que cuando implemento el código en Google App Engine, la solicitud saliente todavía funciona, y el XML de respuesta me parece 100% idéntico y correcto, pero la respuesta no se analiza con la siguiente excepción:

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)

He comprobado doble, triple, cuádruple este XML en busca de "caracteres invisibles" o caracteres no codificados en UTF8, etc. Lo miré byte por byte en una matriz de marcas de orden de bytes o algo de esa naturaleza. Nada; pasa todas las pruebas de validación que pude hacerle. Aún más extraño, sucede si también uso un analizador basado en Saxon, pero SOLO en GAE, siempre funciona bien en mi entorno local.

Hace que sea muy difícil rastrear el código en busca de problemas cuando solo puedo ejecutar el depurador en un entorno que funciona perfectamente (no he encontrado ninguna buena manera de depurar de forma remota en GAE). Sin embargo, usando los medios primitivos que tengo, probé un millón de enfoques que incluyen:

  • XML con y sin prólogo
  • Con y sin nuevas líneas
  • Con y sin el atributo "encoding =" en el prólogo
  • Ambos estilos de nueva línea
  • Con y sin la información fragmentada presente en el flujo HTTP

Y probé la mayoría de estos en múltiples combinaciones donde tenía sentido que interactuaran, ¡nada! Estoy al final de mi ingenio. ¿Alguien ha visto un problema como este antes que, con suerte, pueda arrojar algo de luz sobre él?

¡Gracias!

Adrian Petrescu
fuente
Probablemente necesitemos ver más código. Otra posibilidad es que localmente no se fragmente mientras está en GAE. ¿Cómo maneja el código antes de pasarlo al analizador?
Romain Hippeau
También consideré la posibilidad de fragmentación, pero no parece ser el caso, ya que el mensaje de error que arroja el analizador contiene todo el XML allí mismo (está pegado arriba). El código SDK modificado completo se puede encontrar en github.com/AdrianP/aws-sdk-for-java (mira las confirmaciones más recientes) pero hay MUCHO código allí. Intentaré crear una muestra reproducible más pequeña pronto, aunque incluso eso será difícil. Es un software muy complicado ... ¡Gracias por tus comentarios! :)
Adrian Petrescu
@Raedwald, no creo que sea mi pregunta la duplicada, ya que mi pregunta fue publicada un año antes que esa :)
Adrian Petrescu
1
Este debería ser un ejemplo de cómo se debe hacer una pregunta en SO, leerla me dio varias ideas sobre cómo depurar como desarrollador (gracias OP)
Sudip Bhandari

Respuestas:

129

La codificación en su XML y XSD (o DTD) son diferentes.
Encabezado del archivo XML: <?xml version='1.0' encoding='utf-8'?>
encabezado del archivo XSD:<?xml version='1.0' encoding='utf-16'?>

Otro escenario posible que causa esto es cuando algo viene antes de la declaración del tipo de documento XML. es decir, es posible que tenga algo como esto en el búfer:

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

o incluso un espacio o carácter especial.

Hay algunos caracteres especiales llamados marcadores de orden de bytes que podrían estar en el búfer. Antes de pasar el búfer al analizador, haga esto ...

String xml = "<?xml ...";
xml = xml.trim().replaceFirst("^([\\W]+)<","<");
Romain Hippeau
fuente
Hola Romain, gracias por la respuesta! He comprobado dos y tres veces que no haya nada en el búfer antes del prólogo (incluidos los caracteres ocultos), pero simplemente no hay nada más allí. Sin embargo, intentaré cambiar a la codificación utf-16; por curiosidad, ¿de dónde sacaste la información de que el XSD usa UTF-16?
Adrian Petrescu
@Adrian Petrescu Lo sentimos, estos son solo ejemplos. Si está utilizando DTD o XSD, asegúrese de que coincidan con su XML. Antes de analizar el XML, capturarlo en una cadena y rodearlo con '|' e imprimirlo en la consola. Esto le dirá si está pasando algunos caracteres adicionales.
Romain Hippeau
Ah, ya veo :) Desafortunadamente, lo intenté y no parece ser el caso en esta situación. ¡Gracias de cualquier manera!
Adrian Petrescu
1
¡Gracias! Esto también me salvó. xml.trim (). replaceFirst ("^ ([\\ W] +) <", "<");
stackoverflow
2
Alguien haga que esta sea la respuesta aceptada. Resolvió mi problema de inmediato. Estaba analizando un mensaje que comenzaba con "Mensaje: <? Versión xml ...." El problema era el texto antes del bit xml. Gracias :)
Ric Jafe
8

Este mensaje de error siempre es causado por el contenido XML no válido en el elemento inicial. Por ejemplo, un punto extra pequeño "." al comienzo del elemento XML.

Cualquier carácter antes de " <?xml…." provocará el mensaje de error " org.xml.sax.SAXParseException: Contenido no permitido en el prólogo ".

Un pequeño punto ” . " antes de“<?xml….

Para solucionarlo, simplemente elimine todos esos caracteres extraños antes del “<?xml“.

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

Sunmit Girme
fuente
3
Debe mencionar dónde hizo referencia a que mkyong.com/java/sax-error-content-is-not-allowed-in-prolog
arulraj.net
5

Estaba enfrentando el mismo problema. En mi caso, los archivos XML se generaron desde el programa c # y se enviaron a AS400 para su posterior procesamiento. Después de un análisis, identifiqué que estaba usando codificación UTF8 mientras generaba archivos XML mientras que javac (en AS400) usa "UTF8 sin BOM". Entonces, tuve que escribir un código adicional similar al que se menciona a continuación:

//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
Saturno CAU
fuente
5

Tuve un problema al inspeccionar el archivo xml en notepad ++ y guardar el archivo, aunque tenía la etiqueta xml utf-8 superior como <?xml version="1.0" encoding="utf-8"?>

Se solucionó al guardar el archivo en notpad ++ con Codificación (Tab)> Codificar en UTF-8: seleccionado (fue Codificar en UTF-8-BOM)

techloris_109
fuente
3

Eliminar la declaración xml lo resolvió

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

En mi archivo xml, el encabezado se veía así:

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

En un archivo de prueba, estaba leyendo los bytes del archivo y decodificando los datos como UTF-8 (sin darme cuenta de que el encabezado en este archivo era utf-16) para crear una cadena.

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

Cuando intenté deserializar esta cadena en un objeto, estaba viendo el mismo error:

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

Cuando actualicé la segunda línea a

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

Pude deserializar el objeto sin problemas. Entonces, como Romain señaló anteriormente, las codificaciones deben coincidir.

dfritch
fuente
1

Estaba enfrentando el mismo problema llamado "El contenido no está permitido en el prólogo" en mi archivo xml.

Solución

Inicialmente, mi carpeta raíz era '# Nombre de archivo '.

Cuando eliminé el primer carácter '#', el error se resolvió.

No es necesario eliminar el #filename ... Inténtelo de esta manera ...

En lugar de pasar un objeto File o URL al método unmarshaller, use FileInputStream.

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

Razón inesperada: #carácter en la ruta del archivo

Debido a algún error interno, el error Contenido no permitido en el prólogo también aparece si el contenido del archivo en sí es 100% correcto, pero está proporcionando el nombre del archivo como C:\Data\#22\file.xml.

Esto posiblemente también se aplique a otros caracteres especiales.

Cómo verificarlo: Si mueve su archivo a una ruta sin caracteres especiales y el error desaparece, entonces fue este problema.

miroxlav
fuente
1

Recibí el mismo mensaje de error hoy. La solución fue cambiar el documento de UTF-8 con BOM a UTF-8 sin BOM

matjung
fuente
Tuve el mismo problema. Cambiar el formato de archivo resolvió el problema. ¡Gracias!
code_fish
0

Tenía un carácter de tabulación en lugar de espacios. Reemplazar la pestaña '\ t' solucionó el problema.

Corta y pega todo el documento en un editor como Notepad ++ y muestra todos los caracteres.

SoloPilot
fuente
0

En mi caso del problema, la solución fue reemplazar diéresis alemanas (äöü) con sus equivalentes HTML ...

MBaas
fuente
0

A continuación se muestran las causas anteriores a la excepción "org.xml.sax.SAXParseException: el contenido no está permitido en el prólogo".

  1. Primero verifique la ruta del archivo de schema.xsd y file.xml.
  2. La codificación en su XML y XSD (o DTD) debe ser la misma.
    Encabezado del archivo XML: <?xml version='1.0' encoding='utf-8'?>
    encabezado del archivo XSD:<?xml version='1.0' encoding='utf-8'?>
  3. si algo viene antes de la declaración del tipo de documento XML. es decir: hello<?xml version='1.0' encoding='utf-16'?>
Avinash Dubey
fuente
0

Con el espíritu de "eliminar todos esos caracteres extraños antes del <? Xml", aquí está mi código Java, que funciona bien con la entrada a través de un 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, los bytes que estaba viendo son (en decimal): 239, 187, 191.

Tamias
fuente