read parser open node manage how documentbuilderfactory and java xml xml-parsing xml-validation

parser - xmldocument java



¿Cómo analizar XML inválido(mal/mal formado)? (4)

En mi opinión, estos casos deben resolverse utilizando JSoup .

A continuación se muestra una respuesta no realmente para este caso específico, pero la encontré en la web (gracias a inuyasha82 en Coderwall). Este bit de código me inspiró para otro problema similar al tratar con XML mal formados, así que lo comparto aquí.

No edite lo que se muestra a continuación, tal como está en el sitio web original.

El formato XML requiere que sea válido un elemento raíz único declarado en el documento. Entonces, por ejemplo, un xml válido es:

<root> <element>...</element> <element>...</element> </root>

Pero si tienes un documento como:

<element>...</element> <element>...</element> <element>...</element> <element>...</element>

Esto se considerará un XML con formato incorrecto, por lo que muchos analizadores xml simplemente lanzan una excepción quejándose de que no hay elemento raíz. Etc.

En este ejemplo, hay una solución sobre cómo resolver ese problema y analizar con éxito el xml mal formado anterior.

Básicamente, lo que haremos es agregar mediante programación un elemento raíz.

Entonces, antes que nada, debe abrir el recurso que contiene su xml "malformado" (es decir, un archivo):

File file = new File(pathtofile);

Luego abra un FileInputStream:

FileInputStream fis = new FileInputStream(file);

Si intentamos analizar esta secuencia con cualquier biblioteca XML en ese punto, generaremos la excepción de documento con formato incorrecto.

Ahora creamos una lista de objetos InputStream con tres elementos:

Un elemento ByteIputStream que contiene la cadena: "" Nuestro FileInputStream Un ByteInputStream con la cadena: "" Entonces el código es:

List<InputStream> streams = Arrays.asList( new ByteArrayInputStream("<root>".getBytes()), fis, new ByteArrayInputStream("</root>".getBytes()));

Ahora usando un SequenceInputStream, creamos un contenedor para la Lista creada anteriormente:

InputStream cntr = new SequenceInputStream(Collections.enumeration(str));

Ahora podemos usar cualquier biblioteca XML Parser, en el cntr, y se analizará sin ningún problema. (Comprobado con la biblioteca Stax);

Actualmente, estoy trabajando en una función que implica analizar XML que recibimos de otro producto. Decidí realizar algunas pruebas contra algunos datos reales del cliente, y parece que el otro producto está permitiendo la entrada de usuarios que deberían considerarse inválidos. De todos modos, todavía tengo que intentar encontrar una manera de analizarlo. Estamos usando javax.xml.parsers.DocumentBuilder y javax.xml.parsers.DocumentBuilder un error en la entrada que se parece a lo siguiente.

<xml> ... <description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description> ... </xml>

Como puede ver, la descripción tiene lo que parece ser una etiqueta no válida dentro de ella ( <THIS-IS-PART-OF-DESCRIPTION> ). Ahora, se sabe que esta etiqueta de descripción es una etiqueta de hoja y no debe tener etiquetas anidadas dentro de ella. De todos modos, esto sigue siendo un problema y produce una excepción en DocumentBuilder.parse(...)

Sé que esto es XML no válido, pero es previsiblemente inválido. ¿Alguna idea sobre una forma de analizar dicha entrada?


Ese "XML" es peor que inválido : no está bien formado ; ver XML bien formado frente a XML válido .

Una evaluación informal de la previsibilidad de las transgresiones no ayuda. Esa información textual no es XML. No hay bibliotecas o herramientas XML conformes que puedan ayudarlo a procesarlo.

Opciones, lo más deseable primero:

  1. Haga que el proveedor solucione el problema por su parte. Exija XML bien formado. (Técnicamente, la frase XML bien formado es redundante pero puede ser útil para enfatizar).
  2. Use un analizador de marcado tolerante para limpiar el problema antes de analizarlo como XML:

  3. Procese los datos como texto manualmente usando un editor de texto o programáticamente usando funciones de caracteres / cadenas. Hacer esto mediante programación puede variar de complicado a imposible, ya que lo que parece ser predecible a menudo no lo es: el incumplimiento de las reglas rara vez está sujeto a las reglas .

    • Para errores de caracteres no válidos , use regex para eliminar / reemplazar caracteres no válidos:
      • PHP: preg_replace(''/[^/x{0009}/x{000a}/x{000d}/x{0020}-/x{D7FF}/x{E000}-/x{FFFD}]+/u'', '' '', $s);
      • Ruby: string.tr("^/u{0009}/u{000a}/u{000d}/u{0020}-/u{D7FF}/u{E000‌​}-/u{FFFD}", '' '')
      • Ruby: inputStr.replace(/[^/x09/x0A/x0D/x20-/xFF/x85/xA0-/uD7FF/uE000-/uFDCF/uFDE0-/uFFFD]/gm, '''')
    • Para los símbolos , use regex para reemplazar las coincidencias con &amp; : crédito: blhsin , demo

      &(?!(?:#/d+|#x[0-9a-f]+|/w+);)

    Tenga en cuenta que las expresiones regulares anteriores no tendrán en cuenta los comentarios o las secciones CDATA.


La respuesta aceptada es un buen consejo y contiene enlaces muy útiles.

Me gustaría agregar que esto y many other casos de XML no bien formado y / o inválido DTD pueden repararse usando SGML, el superconjunto de HTML y XML estandarizado por ISO. En su caso, lo que funciona es declarar el elemento falso THIS-IS-PART-OF-DESCRIPTION como elemento vacío SGML y luego usar, por ejemplo. el programa osx (parte del paquete OpenSP / OpenJade SGML) para convertirlo a XML. Por ejemplo, si proporciona lo siguiente a osx

<!DOCTYPE xml [ <!ELEMENT xml - - ANY> <!ELEMENT description - - ANY> <!ELEMENT THIS-IS-PART-OF-DESCRIPTION - - EMPTY> ]> <xml> <description>blah blah <THIS-IS-PART-OF-DESCRIPTION> </description> </xml>

generará XML bien formado para su posterior procesamiento con las herramientas XML que elija.

Sin embargo, tenga en cuenta que su fragmento de ejemplo tiene otro problema en que los nombres de elementos que comienzan con las letras xml o XML o Xml etc. están reservados en XML y no serán aceptados por analizadores XML conformes.


Un analizador XML estándar NUNCA aceptará XML no válido, por diseño.

Su única opción es preprocesar la entrada para eliminar el contenido "previsiblemente inválido", o envolverlo en CDATA, antes de analizarlo.