2011-03-22 11 views
11

conoce la función en java que validará una cadena para que sea un buen nombre de elemento XML.java - ¿Cómo comprobar si string es un nombre de elemento XML válido?

w3schools Forma:

elementos XML deben seguir estos nombres reglas:

  1. nombres pueden contener letras, números y otros caracteres
  2. Los nombres pueden no comenzar con un número o puntuacion carácter
  3. Los nombres no pueden comenzar con las letras xml (o XML, o Xml, etc.)
  4. Los nombres no pueden contener espacios

me encontré con otras preguntas que ofrecen soluciones de expresiones regulares, no hay una función que ya se hace eso?

Respuesta

13

Si está usando Xerces analizador XML, se puede utilizar el XMLCHAR (o XML11Char) clase isValidName() method, así:

org.apache.xerces.util.XMLChar.isValidName(String name) 

También existe código de ejemplo para available hereisValidName.

+1

Bien, parece exactamente lo que estoy buscando, pero ¿sabes por qué XMLChar.isValidName ("xml") devuelve verdadero? (Pregunta aprobada) – ekeren

+1

"xml", medido con insensibilidad a las mayúsculas y minúsculas, es válido, pero está reservado. Puede encontrarlo en la práctica. Si está buscando entradas, es posible que desee agregar &&! Name.toLowerCase(). StartsWith ("xml") – lavinio

+0

El código requerido para la verificación de la validez del nombre en realidad consiste de solo unas pocas líneas y se puede copiar para evitar otro dependencia externa. Ver [mi respuesta] (http://stackoverflow.com/a/34560639/1125413) para más detalles. – pemistahl

4

La producción relevante de la especificación es http://www.w3.org/TR/xml/#NT-Name

Nombre :: == NameStartChar NameChar *

NameStartChar :: = ":" | [A-Z] | "_" | [a-z] | [# xC0- # xD6] | [# xD8- # xF6] | [# xF8- # x2FF] | [# x370- # x37D] | [# x37F- # x1FFF] | [# x200C- # x200D] | [# x2070- # x218F] | [# x2C00- # x2FEF] | [# x3001- # xD7FF] | [# xF900- # xFDCF] | [# xFDF0- # xFFFD] | [# x10000- # xEFFFF]

NameChar :: = NameStartChar | "-" | "." | [0-9] | # xB7 | [# x0300- # x036F] | [# # X203F- X2040]

lo tanto una expresión regular para que coincida es

"^[:A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" 
+ "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\ud7ff" 
+ "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\x10000-\\xEFFFF]" 
+ "[:A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6" 
+ "\\u00F8-\\u02ff\\u0370-\\u037d\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f" 
+ "\\u2c00-\\u2fef\\u3001-\\udfff\\uf900-\\ufdcf\\ufdf0-\\ufffd\\-\\.0-9" 
+ "\\u00b7\\u0300-\\u036f\\u203f-\\u2040]*\\Z" 

Si usted quiere tratar con nombres de espacios de nombres, es necesario asegurarse de que no es a lo sumo una de colon, por lo

"^[A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" 
+ "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\udfff" 
+ "\\uf900-\\ufdcf\\ufdf0-\\ufffd]" 
+ "[A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" 
+ "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\udfff" 
+ "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\-\\.0-9\\u00b7\\u0300-\\u036f\\u203f-\\u2040]*" 
+ "(?::[A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" 
+ "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\udfff" 
+ "\\uf900-\\ufdcf\\ufdf0-\\ufffd]" 
+ "[A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" 
+ "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\udfff" 
+ "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\-\\.0-9\\u00b7\\u0300-\\u036f\\u203f-\\u2040]*)?\\Z" 

(perdido otra 03gf; cambió tanto a 036f)

+0

Gracias, ¿Esto significa que la regla número 3 no está bien "3. Los nombres no pueden comenzar con el xml cartas (o XML, o XML , etc.) " – ekeren

+0

La respuesta es sí y no. "Los nombres que comienzan con la cadena" xml ", o con cualquier cadena que coincida (('X' | 'x') ('M' | 'm') ('L' | 'l')), están reservados para estandarización en esta o futuras versiones de esta especificación ". Entonces es un nombre válido, pero está reservado. –

1

Usar las utilidades org.apache.xerces es una buena forma de hacerlo; sin embargo, si es necesario atenerse al código Java que es parte de la API estándar de Java, entonces el siguiente código hará:

public void parse(String xml) throws Exception { 

    XMLReader parser = XMLReaderFactory.createXMLReader(); 
    parser.setContentHandler(new DefaultHandler()); 
    InputSource source = new InputSource(new ByteArrayInputStream(xml.getBytes())); 
    parser.parse(source); 
} 
+0

Pero tenga en cuenta que la sobrecarga de instanciar un XMLReader para esta tarea es bastante alta, especialmente si se hace usando la búsqueda de fábrica de JAXP. No hay problema si se reutiliza con la suficiente frecuencia, por supuesto. –

2

Como una adición actual a la accepted answer:

Al menos JDK de Oracle 1.8 (probablemente también los más antiguos) usan el analizador Xerces internamente en los paquetes no públicos com.sun.*. Nunca debe usar directamente ninguna implementación de esas clases, ya que pueden cambiar sin previo aviso en futuras versiones del JDK.Sin embargo, el código requerido para la verificación de validez del nombre del elemento xml está muy bien encapsulado y se puede copiar a su propio código. De esta forma, puede evitar otra dependencia a una biblioteca externa.

Este es el código requerido tomado de la clase interna com.sun.org.apache.xerces.internal.util.XMLChar:

public class XMLChar { 

    /** Character flags. */ 
    private static final byte[] CHARS = new byte[1 << 16]; 

    /** Name start character mask. */ 
    public static final int MASK_NAME_START = 0x04; 

    /** Name character mask. */ 
    public static final int MASK_NAME = 0x08; 

    static { 
     // Initializing the Character Flag Array 
     // Code generated by: XMLCharGenerator. 

     CHARS[9] = 35; 
     CHARS[10] = 19; 
     CHARS[13] = 19; 

     // ... 
     // the entire static block must be copied 
    } 

    /** 
    * Check to see if a string is a valid Name according to [5] 
    * in the XML 1.0 Recommendation 
    * 
    * @param name string to check 
    * @return true if name is a valid Name 
    */ 
    public static boolean isValidName(String name) { 
     final int length = name.length(); 
     if (length == 0) { 
      return false; 
     } 
     char ch = name.charAt(0); 
     if (!isNameStart(ch)) { 
      return false; 
     } 
     for (int i = 1; i < length; ++i) { 
      ch = name.charAt(i); 
      if (!isName(ch)) { 
       return false; 
      } 
     } 
     return true; 
    } 

    /** 
    * Returns true if the specified character is a valid name start 
    * character as defined by production [5] in the XML 1.0 
    * specification. 
    * 
    * @param c The character to check. 
    */ 
    public static boolean isNameStart(int c) { 
     return c < 0x10000 && (CHARS[c] & MASK_NAME_START) != 0; 
    } 

    /** 
    * Returns true if the specified character is a valid name 
    * character as defined by production [4] in the XML 1.0 
    * specification. 
    * 
    * @param c The character to check. 
    */ 
    public static boolean isName(int c) { 
     return c < 0x10000 && (CHARS[c] & MASK_NAME) != 0; 
    } 
} 
Cuestiones relacionadas