2010-05-14 9 views
24

necesito unescape una cadena XML que contiene escapado etiquetas XML:cómo unescape XML en Java

< 
> 
& 
etc... 

encontré algunas librerías que pueden realizar esta tarea, pero prefiero usar un único método que puede realiza esta tarea.

¿Alguien puede ayudar?

aplausos, Bas Hendriks

Respuesta

40
StringEscapeUtils.unescapeXml(xml) 

(commons-lang, download)

+1

"pero prefiero usar un único método que pueda realizar esta tarea". –

+15

Ese es un método único. – Quentin

+1

Bas, lea el código fuente de commons-lang y vea si vale la pena reinventar la rueda en su caso en lugar de simplemente usarla. –

6

Aquí está un método simple para XML unescape. Maneja las entidades XML predefinidas y las entidades numéricas decimales (& #nnnn;). Modificarlo para manejar entidades hexadecimales (& #xhhhh;) debe ser simple.

public static String unescapeXML(final String xml) 
{ 
    Pattern xmlEntityRegex = Pattern.compile("&(#?)([^;]+);"); 
    //Unfortunately, Matcher requires a StringBuffer instead of a StringBuilder 
    StringBuffer unescapedOutput = new StringBuffer(xml.length()); 

    Matcher m = xmlEntityRegex.matcher(xml); 
    Map<String,String> builtinEntities = null; 
    String entity; 
    String hashmark; 
    String ent; 
    int code; 
    while (m.find()) { 
     ent = m.group(2); 
     hashmark = m.group(1); 
     if ((hashmark != null) && (hashmark.length() > 0)) { 
      code = Integer.parseInt(ent); 
      entity = Character.toString((char) code); 
     } else { 
      //must be a non-numerical entity 
      if (builtinEntities == null) { 
       builtinEntities = buildBuiltinXMLEntityMap(); 
      } 
      entity = builtinEntities.get(ent); 
      if (entity == null) { 
       //not a known entity - ignore it 
       entity = "&" + ent + ';'; 
      } 
     } 
     m.appendReplacement(unescapedOutput, entity); 
    } 
    m.appendTail(unescapedOutput); 

    return unescapedOutput.toString(); 
} 

private static Map<String,String> buildBuiltinXMLEntityMap() 
{ 
    Map<String,String> entities = new HashMap<String,String>(10); 
    entities.put("lt", "<"); 
    entities.put("gt", ">"); 
    entities.put("amp", "&"); 
    entities.put("apos", "'"); 
    entities.put("quot", "\""); 
    return entities; 
} 
3

Aquí es uno que escribí en diez minutos. No usa expresiones regulares, solo iteraciones simples. No creo que esto se pueda mejorar para ser mucho más rápido.

public static String unescape(final String text) { 
    StringBuilder result = new StringBuilder(text.length()); 
    int i = 0; 
    int n = text.length(); 
    while (i < n) { 
     char charAt = text.charAt(i); 
     if (charAt != '&') { 
      result.append(charAt); 
      i++; 
     } else { 
      if (text.startsWith("&amp;", i)) { 
       result.append('&'); 
       i += 5; 
      } else if (text.startsWith("&apos;", i)) { 
       result.append('\''); 
       i += 6; 
      } else if (text.startsWith("&quot;", i)) { 
       result.append('"'); 
       i += 6; 
      } else if (text.startsWith("&lt;", i)) { 
       result.append('<'); 
       i += 4; 
      } else if (text.startsWith("&gt;", i)) { 
       result.append('>'); 
       i += 4; 
      } else i++; 
     } 
    } 
    return result.toString(); 
}