XML es un metalenguaje que nos permite jerarquizar y estructurar la información así como describir los contenidos dentro del propio documento. Son ficheros de texto con información almacenada de forma secuancial y estructurada. Las marcas especiales que nos permiten delimitar el contenido y la estructura son los símbolos de “>” y “<“. Cada marca tiene un nombre y puede tner 0 o más atributos.
<?xml version="1.0"> <Empleados> <empleado id="1"> <apellido>Martinez</apellido> <dep>10</dep> <salario>1000.33</slario> </empleado> <empleado id="2"> <apellido>Garcia</apellido> <dep>11</dep> <salario>2000.34</slario> </empleado> <empleado id="3"> <apellido>Navarro</apellido> <dep>10</dep> <salario>2222.33</slario> </empleado> </Empleados>
Para leer los ficherosXML y acceder a su contenido y estructura, se utiliza el procesador de XML o parser. Algunos de los procesadores más utilizados son:
- DOM = Modelo de Objetos de Documentos
- SAX = API Simple para XML
DOM: almacena toda la estructura del documento en forma de árbol. Necesita más recursos y memoria.
SAX: apenas consume memoria, pero impide tener una visión global del documento. Lee de forma secuencial y produce una secuencia de eventos (inicio/fin de documento; inicio/fin de etiqueta; etc.) donde cada evento invocará un método definido por el programador.
ACCESO A FICHEROS XML CON DOM
Paquetes necesarios:
Estas clases e interfaces ofrecen métodos para cargar documentos desde una fuente de datos (File, InputStream, etc.)
Pero hay dos clases fundamentales:
Los programas Java que utilicen DOM necesitan principalmente estas interfaces:
- Document: objeto que equivale a un ejemplar de un documento XML, permite crear nuevos nodos.
- Element: Cada elemento del documento XML tiene un equivalente en un objeto de este tipo. Expone propiedades y métodos para manipular los elementos del documento y sus atributos.
- Node: Representa a cualquier nodo del documento.
- NodeList: Contiene una lista con los nodos hijos de un nodo.
- Attr: Permite acceder a los atributos de un nodo.
- Text: Son los datos carácter de un elemento.
- CharacterData: Representa a los datos carácter del documento.
- DocumentType: Proporciona información contenida en la etiqueta <!DOCTYPE>.
Lectura de un fichero XML
... File file = new File("empleados.xml"); ... try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(file); } catch(Exception e) { e.printStackTrace(); }
Una vez hecho todo esto ya podremos leer el archivo empleados.xml además de usar otros métodos como los ejemplos de aquí abajo.
Método | Descripción |
---|---|
getDocumentElement() | Accede al nodo raíz del documento |
normalize() | Elimina nodos vacíos y combina adyacentes en caso de que los hubiera |
... // estos métodos podemos usarlos combinados para normalizar el archivo XML doc.getDocumentElement().normalize(); ...
Siguiendo dentro del try/catch podemos utilizar la clase NodeList para almacenar el elemento que le indicaremos como parámetro.
// almacenamos los nodos para luego mostrar la // cantidad de ellos con el método getLength() NodeList nList = doc.getElementsByTagName("empleado"); System.out.println("Número de empleados: " + nList.getLength());
Una vez tenemos almacenados los datos del nodo “empleado” podemos leer su contenido teniendo en cuenta que este código depende de que conozcamos la estructura y etiquetas utilizadas.
for(int temp = 0; temp < nList.getLength(); temp++) { Node nNode = nList.item(temp); if(nNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) nNode; System.out.println("\nEmpleado id: " + eElement.getAttribute("id")); System.out.println("Apellido: " + eElement.getElementsByTagName("apellido").item(0).getTextContent()); System.out.println("Departamento: " + eElement.getElementsByTagName("dep").item(0).getTextContent()); System.out.println("Salario: " + eElement.getElementsByTagName("salario").item(0).getTextContent()); } }
Si no conocemos la estructura podemos utilizar el código de más abajo para leer el archivo XML.
NodeList nList = doc.getElementsByTagName("empleado"); for (int i = 0; i < nList.getLength(); i++) { Node node = nList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) node; if(eElement.hasChildNodes()) { NodeList nl = node.getChildNodes(); for(int j=0; j<nl.getLength(); j++) { Node nd = nl.item(j); System.out.println(nd.getTextContent()); } } } }
Escritura de un fichero XML
Si quisiéramos escribir un archivo XML siguiendo la misma estructura del concesionario deberíamos instanciar las clases DocumentBuilderFactory, DocumentBuilder y Document, definir toda la estructura del archivo (siempre dentro de un bloque try/catch) y por último instanciar las clases TransformerFactory, Transformer, DOMSource y StreamResult para crear el archivo.
try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); // definimos el elemento raíz del documento Element eRaiz = doc.createElement("concesionario"); doc.appendChild(eRaiz); // definimos el nodo que contendrá los elementos Element eCoche = doc.createElement("coche"); eRaiz.appendChild(eCoche); // atributo para el nodo coche Attr attr = doc.createAttribute("id"); attr.setValue("1"); eCoche.setAttributeNode(attr); // definimos cada uno de los elementos y le asignamos un valor Element eMarca = doc.createElement("marca"); eMarca.appendChild(doc.createTextNode("Renault")); eCoche.appendChild(eMarca); Element eModelo = doc.createElement("modelo"); eModelo.appendChild(doc.createTextNode("Megano")); eCoche.appendChild(eModelo); Element eCilindrada = doc.createElement("cilindrada"); eCilindrada.appendChild(doc.createTextNode("1.5")); eCoche.appendChild(eCilindrada); // clases necesarias finalizar la creación del archivo XML TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File("coches.xml")); transformer.transform(source, result); } catch(Exception e) { e.printStackTrace(); }
Utilizando objetos y Array
public class Coche { private String marca; private String modelo; private String cilindrada; public Coches() { marca = "Renault"; modelo = "Megane"; cilindrada = "1.5"; } public Coches(String nombre, String creador, String ciudad) { this.marca = nombre; this.modelo = creador; this.cilindrada = ciudad; } @Override public String toString() { return this.marca.replace(' ', '_') + " " + this.modelo.replace(' ', '_') + " " + this.cilindrada.replace(' ', '_'); } }
Y la instacia sería:
... Coche coche = new Coche("Seat", "León", "1.5"); ...
Utilizando el fichero “AleatorioEmple.dat” utilizado en ejercicios anteriores vamos realizar un programa que lea los empleados creados en dicho archivo y los guarde en un fichero XML.
Librería jar_files
package pkgCrearEmpleadoXml; import org.w3c.dom.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import java.io.*; public class CrearEmpleadoXml { public static void main(String[] args) throws IOException{ File f = new File("C:\\Users\\Victor\\Documents\\ADA\\T0\\AleatorioEmple\\lib\\FichData.dat"); RandomAccessFile raf = new RandomAccessFile(f, "r"); int id, departamento; float salario; String apellidoS; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); DOMImplementation implementation = builder.getDOMImplementation(); Document document = implementation.createDocument(null, "Empleados", null); document.setXmlVersion("1.0"); for(;;) { id = raf.readInt(); apellidoS = raf.readUTF(); departamento = raf.readInt(); salario = raf.readFloat(); System.out.println("ID: " + id + "; Apellido: " + apellidoS + "; Departamento: " + departamento + "; Salario: " + salario); Element raiz = document.createElement("empleado"); document.getDocumentElement().appendChild(raiz); crearElemento("ID",Integer.toString(id),raiz,document); // añadir ID crearElemento("apellido",apellidoS.trim(),raiz,document); // añadir apellido crearElemento("departamento",Integer.toString(departamento),raiz,document); // añadir DEP crearElemento("salario",Float.toString(salario),raiz,document); // añadir salario if (raf.getFilePointer() >= raf.length()) break; } Source source = new DOMSource(document); Result result = new StreamResult (new File("lib\\Empleados.xml")); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.transform(source,result); }catch(EOFException eofe) { System.out.println("Error End Of File: " + eofe.getMessage()); }catch(IOException e) { System.out.println("Error IO: " + e.getMessage()); }catch(TransformerConfigurationException tce) { System.out.println("Error Transformer Configuration: " + tce.getMessage()); }catch(TransformerException te) { System.out.println("Error Transformer: " + te.getMessage()); }catch(ParserConfigurationException pce) { System.out.println("Error Parser Configuration: " + pce.getMessage()); }finally { raf.close(); } } static void crearElemento(String datoEmpleado, String valor, Element raiz, Document document) { Element elem = document.createElement (datoEmpleado); //creamos hijo Text text = document.createTextNode(valor); // damos valor al campo raiz.appendChild(elem); //pegamos el elemento hijo a la raiz elem.appendChild(text); //pegamos el valor } }
Sube ambos ejercicios a tu repositorio GIT en 2dam.fp.edu.es
No olvides crear el fichero README.md y explicar en el mismo que hace tu aplicación y como lo hace.
Ejercicio 10. La lectura de este archivo XML:
- Crear una instacia de DocumentBuilderFactory
- Cargar el documento con el método parser();
Document document = builder.parse(new File(“Empleados.xml”));
- Cargar el documento con el método parser();
- Obtener la lista de nodos con el nombre empleado de todo el documento
- NodeList empleados = document.getElementByTagName(“empleado”);
- Luego con un bucle recorremos la lista
- Para cada nodo obtenemos etiquetas y valores utilizando la función getNodo();
Ejercicio 11. A partir del fichero de objetos Persona crea un XML usando DOM