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