Análisis XML con REGEX en Java

Dado el siguiente fragmento de XML, necesito obtener una lista de pares de nombre / valor para cada hijo en DataElements. XPath o un analizador XML no se pueden usar por razones ajenas a mi control, así que estoy usando regex.

   2.0 95465.00 11.A 13   92f4-MPA 7.19879   

El resultado que necesito es: [{EmpStatus: 2.0}, {Gasto: 95465.00}, {StaffType: 11.A}, {Industria: 13}]

Los nombres de tags en DataElements son dynamics y, por lo tanto, no se pueden express literalmente en la expresión regular. Los nombres de etiqueta TargetCenter y Trace son estáticos y podrían estar en la expresión regular, pero si hay una forma de evitar la encoding rígida sería preferible.

 "([A-Za-z0-9.]*?)</" 

Esta es la expresión regular que he construido y tiene el problema de que incluye erróneamente {Trace: 719879} en los resultados. Confiar en nuevas líneas dentro del XML o cualquier otro formato aparente no es una opción.

A continuación se muestra una aproximación del código de Java que estoy usando:

 private static final Pattern PATTERN_1 = Pattern.compile(..REGEX..); private List listDataElements(CharSequence cs) { List list = new ArrayList(); Matcher matcher = PATTERN_1.matcher(cs); while (matcher.find()) { list.add(new DataElement(matcher.group(1), matcher.group(2))); } return list; } 

¿Cómo puedo cambiar mi expresión regular para incluir solo elementos de datos e ignorar el rest?

Esto debería funcionar en Java, si puede suponer que entre las tags DataElements, todo tiene el valor del formulario. Es decir, sin atributos ni elementos nesteds.

 Pattern regex = Pattern.compile("(.*?)", Pattern.DOTALL); Matcher matcher = regex.matcher(subjectString); Pattern regex2 = Pattern.compile("<([^<>]+)>([^<>]+)"); if (matcher.find()) { String DataElements = matcher.group(1); Matcher matcher2 = regex2.matcher(DataElements); while (matcher2.find()) { list.add(new DataElement(matcher2.group(1), matcher2.group(2))); } } 

XML no es un lenguaje regular. No puede analizarlo usando una expresión regular. Una expresión que crees que funcionará se romperá cuando obtengas tags anidadas, y cuando lo arregles se romperá con los comentarios XML, luego con las secciones CDATA, las directivas del procesador, los espacios de nombres, … No puede funcionar, usa un analizador XML.

¡Usa XPath en su lugar!

Deberías usar una biblioteca XML para esto.

Si tiene que usar RE, ¿por qué no hacerlo en dos etapas? DataElements>.*? entonces lo que tienes ahora.

¿Hay alguna razón por la que no esté utilizando un analizador XML adecuado en lugar de regex? Esto sería trivial con la biblioteca correcta.

Perdón por darle otra respuesta “No usar expresiones regulares”, pero en serio. Utilice Commons-Digester , JAXP (incluido con Java 5+) o JAXB (incluido con Java 6+), ya que lo salvará de una carga de daño.

Deberías escuchar a todos. Un analizador liviano es una mala idea.

Sin embargo, si realmente es tan duro al respecto, debería poder ajustar su código para excluir las tags fuera de la etiqueta DataElements.

 private static final Pattern PATTERN_1 = Pattern.compile(..REGEX..); private static final String START_TAG = ""; private static final String END_TAG = ""; private List listDataElements(String input) { String cs = input.substring(input.indexOf(START_TAG) + START_TAG.length(), input.indexOf(END_TAG); List list = new ArrayList(); Matcher matcher = PATTERN_1.matcher(cs); while (matcher.find()) { list.add(new DataElement(matcher.group(1), matcher.group(2))); } return list; } 

Esto fallará horriblemente si la etiqueta de datos no existe.

Una vez más, esta es una mala idea, y es probable que vuelva a visitar este fragmento de código en el futuro en forma de informe de error.

Intente analizar el Reg Ex a través de un archivo de propiedad y cree el objeto de patrón. Resolví el mismo problema que enfrenté al inyectar Reg Ex a través de xml beans.

Ejemplo: – Necesitaba analizar el Reg Ex ‘(.) (D [0-9] {7} .D [0-9] {9} .D [AZ] {3} [0-9] {4} ) (.) ‘por inyección en spring. Pero no funcionó. Una vez intentado utilizar el mismo Reg Ex codificado en una clase Java funcionó.

Patrón de patrón = Pattern.compile (“(.) (D [0-9] {7} .D [0-9] {9} .D [AZ] {2} [0-9] {4}) (. ) “); Matcher matcher = pattern.matcher (file.getName (). Trim ());

 Next I tried to load that Reg Ex via property file while injecting it. It worked fine. p:remoteDirectory="${rawDailyReport.remote.download.dir}" p:localDirectory="${rawDailyReport.local.valid.dir}" p:redEx="${rawDailyReport.download.regex}" 

Y en el archivo de propiedades, la propiedad se define de la siguiente manera.

rawDailyReport.download.regex = (. ) (D [0-9] {7} \. D [0-9] {9} \. D [AZ] {2} [0-9] {4}) (. )

Esto se debe a que los valores con marcadores de posición se cargan a través de org.springframework.beans.factory.config.PropertyPlaceholderConfigurer y maneja estos caracteres confidenciales xml internamente.

Gracias, Amith