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:
- 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).
-
Use un analizador de marcado tolerante para limpiar el problema antes de analizarlo como XML:
-
Independiente: xmlstarlet tiene sólidas capacidades de recuperación y reparación crédito: RomanPerekhrest
xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null
-
Standalone y C: HTML Tidy también funciona con XML.
-
Python:
Beautiful Soup
está basado en Python.
Ver notas en la sección
Diferencias entre analizadores
.
Consulte también las
respuestas a esta pregunta
para obtener más sugerencias para lidiar con el marcado no bien formado en Python.
Consulte también
esta respuesta
para
codecs.EncodedFile()
cómo usarcodecs.EncodedFile()
para limpiar caracteres ilegales. -
Java:
JSoup
enfoca en HTML.
FilterInputStream
se puede usar para la limpieza de preprocesamiento . -
.RED:
- XmlReaderSettings.CheckCharacters se puede deshabilitar para superar problemas ilegales de caracteres XML.
-
@jdweng señala
que
XmlReaderSettings.ConformanceLevel
se puede establecer enConformanceLevel.Fragment
para queXmlReader
pueda leer entidades analizadas XML bien formadas que carecen de un elemento raíz. -
@jdweng también informa
que
XmlReader.ReadToFollowing()
veces se puede usar para solucionar problemas sintácticos XML , pero tenga en cuenta la advertencia de ruptura de reglas en el # 3 a continuación. -
Se dice que
Microsoft.Language.Xml.XMLParser
es "tolerante a errores".
- PHP: Ver DOMDocument::$recover libxml_use_internal_errors(true) y libxml_use_internal_errors(true) . Ver buen ejemplo here .
- Ruby: Nokogiri apoya " Gentle Well-Formedness ".
- R: Ver htmlTreeParse() para el análisis de marcado tolerante a fallas en R.
-
-
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:
-
Para los símbolos , use regex para reemplazar las coincidencias con
&
: 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.