Home| New Wiki | | Login | User registry | Home Tree PDF
XML y DOM y normas de programacion
Owner:csilva, Version: 9, Date:Mon 15, November 2004,

Para usar XML la forma mas facil es usar DOM. En DOM, un archivo XML es llevado a un objeto en memoria de tipo Document y con funciones se puede "navegar" por el contenido.

Ahora, normalmente, el codigo que accede a la informacion de un XML con DOM puede ser asi:

public void procesa(String parameterXML) {
 DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 StringReader reader = new StringReader(parameterXML);
 InputSource source = new InputSource(reader);
 Document document = docBuilder.parse(source);
 NodeList nl = doc.getChildNodes();
 Node n1 = nl.item(0);
 Node n2 = n1.getChildNodes().item(2);
 Node n3 = n2.getChildNodes().item(1);
 Node n4 = n3.getChildNodes().item(1);
 String origen = n4.getChildNodes().item(0).getNodeValue();
 String destino= n4.getChildNodes().item(1).getNodeValue();
}

Este codigo tiene varios problemas, entre ellos:

#Los hijos de un nodo pueden ser valores o comentarios o espacios en blanco entre otros tags

#La posicion de un hijo no es fija por que hay elementos opcionales o con repeticiones

Ahora, para usar funciones que sirvan en el futuro como referencia es importante esforzarse en crear aquellas funciones que representen lo que uno quiere. Esto a veces significa proponer una especificacion que ayude a resolver el problema:

En este caso:

0) Aislarse de los detalles de implementacion de parsers de XML. Solucion:

/**
 * Transforma a document un String con el XML
 */
private Document getDocumentFromXML(String parameterXML) 
        throws  ParserConfigurationException, SAXException, IOException {
 DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 StringReader reader = new StringReader(parameterXML);
 InputSource source = new InputSource(reader);
 Document document = docBuilder.parse(source);
 return document;
}

1) Los hijos de un nodo pueden ser valores o comentarios o espacios en blanco entre otros tags. Solucion:

/**
 * Retorna la primera aparicion de un nodo hijo con el tipo indicado.
 * @param n Nodo desde el cual buscar
 * @param type tipo del hijo buscado (tag) segun las constantes de la clase Node.
 */
static Node getChildByType(Node n, int type) {
 NodeList nl = n.getChildNodes();
 for (int i = 0; i < nl.getLength(); i++) {
  Node t = nl.item(i);
  if (t.getNodeType() == type)
   return t;
 }
 return null;
}

2) A veces se requiere encontrar un hijo, pero su posicion no esta clara debido a que hay comentarios u otros tags opcionales en la lista. Solucion: buscar por el nombre del tag

/**
 * Retorna la primera aparicion de un nodo hijo con el nombre indicado.
 * @param n Nodo desde el cual buscar
 * @param name nombre del hijo buscado (tag)
 */
static Node getChildByName(Node n, String name) {
 NodeList nl = n.getChildNodes();
 for (int i = 0; i < nl.getLength(); i++) {
 Node t = nl.item(i);
 if (t.getNodeName().equals(name))
  return t;
 }
 return null;
}

3) En muchos casos se requiere obtener un nodo que tiene un camino dentro del XML y es mas facil especificar el camino como si fuera un PATH de S.O.: PRoject/Color/Default/Task/Line. Solucion:

/**
 * Retorna la primera aparicion de un nodo con el path indicado.
 * @param n Documento desde el cual buscar (raiz)
 * @param name path del nodo buscado con nodos separados por slash (/)
 */
static Node getElementByPath(Document doc, String path) { 
  StringTokenizer st = new StringTokenizer(path, "/");
  Node n = doc;
  while (st.hasMoreTokens()) {
    String t = st.nextToken();
    n = getChildByName(n, t);
    if (n == null)
      return null;
  }
  return n;
}

4) Normalmente la mayoria de las preguntas sobre XML cuando se usa DOM tienen que ver con texto y contenido, para codificar rapidamente se requiren funciones cercanas a lo necesario. Solucion:

/**
 * Retorna la primera aparicion de un nodo con el path indicado.
 * @param n Documento desde el cual buscar (raiz)
 * @param name path del nodo buscado con nodos separados por slash  (/)
 */
static String getElementText(Document doc, String path) {
 Node n = getElementByPath(doc, path);
 Node v = getChildByType(n, Node.TEXT_NODE);
 return v.getNodeValue();
}

Finalmente

Ejemplo de la aplicacion del codigo anterior:

/**
 * Genera un nombre concatenando nombre y apellido del XML
 */
private String getName(String paramXML){
 Documento document = getDocumentFromXML(paramXML);
 String fileName = null;
 String nombre = getElementText(document,
   "Empresa/Administrador/Nombre");
 String apellido  = getElementText(document,
   "Empresa/Administrador/Apellido");
 return nombre.trim() +" "+ destino.trim();
}

Notas

  • falla si el elemento Empresa se repite ??
  • falla si Administrador es opcional?


Edit - History - Extract PDF - Extract Tree as PDF

Last Modified

Thu, Nov 19 Sat, Oct 3 Fri, Sep 25 Mon, Aug 3 Mon, Apr 27 Sat, Mar 28 Mon, Jan 19 Tue, Jan 6

Home| New Wiki