Ejercicios
Creación de documentos XML
Enunciado
Construir un documento XML para el siguiente pedido que ha
recibido por correo electrónico una empresa que se dedica a la venta
de herramientas para jardinería:
"Hola, necesito una cortadora de cesped para mi jardín de esas
que anuncian en oferta, me gustaría que fuera uno de esos modelos
eléctricos, pues las de gasolina contaminan mucho. Me llamo Roberto
Movilla, la cortadora la tendrán que enviar a Albacete, la dirección
es Plaza de la Duquesa 12, la recogerá mi esposa que se llama Alicia
Abad. Ahora que lo pienso también necesitaré 3 podadoras para los
setos. Les paso mi dirección de aquí para lo referente al pago, es
General Ricardos 56, aquí en Madrid. Es urgente, por favor, el
césped está muy alto."
La fecha del pedido es el 20 de octubre del 99. El empleado que
se encarga del pedido ha comprobado algunos datos necesarios: el
código postal de la dirección de Albacete es 05020 y el de la de
Madrid 28055; también ha consultado el catálogo de productos y ha
averiguado que la cortadora vale 148.95 euros y su código de
producto es 872-AA, aunque no sabe si es o no eléctrica; una
podadora vale 7.98 y su código es 926-FH.
Solución
<?xml version="1.0" encoding="ISO-8859-1"?>
<Pedido xmlns="http://www.miempresa.org/pedidos"
fecha="1999-10-20">
<Destino>
<Nombre>Alicia Abad</Nombre>
<Direccion>Plaza de la Duquesa 12</Direccion>
<Ciudad>Albacete</Ciudad>
<CodPostal>05020</CodPostal>
</Destino>
<Ordenante>
<Nombre>Roberto Movilla</Nombre>
<Direccion>General Ricardos 56</Direccion>
<Ciudad>Madrid</Ciudad>
<CodPostal>28055</CodPostal>
</Ordenante>
<Observaciones>Es urgente, el césped está muy alto</Observaciones>
<Contenido>
<Producto codigo="872-AA">
<Nombre>Cortadora de cesped</Nombre>
<Cantidad>1</Cantidad>
<Precio>148.95</Precio>
<Observaciones>Confirmar que es eléctrica</Observaciones>
</Producto>
<Producto codigo="926-FH">
<Nombre>Podadora</Nombre>
<Cantidad>3</Cantidad>
<Precio>7.98</Precio>
</Producto>
</Contenido>
</Pedido>
DTDs
Enunciado
Construir un documento DTD para el documento XML del ejercicio
anterior.
Solución
<!DOCTYPE Pedido SYSTEM "Pedido.dtd">
...
<!ELEMENT Pedido (Destino, Ordenante, Observaciones, Contenido)>
<!ATTLIST Pedido
xmlns CDATA #REQUIRED
fecha CDATA #REQUIRED
>
<!ELEMENT Destino (Nombre, Direccion, Ciudad, CodPostal)>
<!ELEMENT Ordenante (Nombre, Direccion, Ciudad, CodPostal)>
<!ELEMENT Nombre (#PCDATA)>
<!ELEMENT Direccion (#PCDATA)>
<!ELEMENT Ciudad (#PCDATA)>
<!ELEMENT CodPostal (#PCDATA)>
<!ELEMENT Observaciones (#PCDATA)>
<!ELEMENT Contenido (Producto+)>
<!ELEMENT Producto (Nombre, Cantidad, Precio, Observaciones?)>
<!ATTLIST Producto
codigo CDATA #REQUIRED
>
<!ELEMENT Cantidad (#PCDATA)>
<!ELEMENT Precio (#PCDATA)>
Esquemas XML
Enunciado
Construir un esquema XML para la siguiente DTD:
<!ELEMENT Libro (Titulo, Contenido, Copyright)>
<!ATTLIST Libro
xmlns CDATA #REQUIRED
>
<!ELEMENT Titulo (#PCDATA)>
<!ELEMENT Contenido ((Capitulo+, Separacion?)+)>
<!ELEMENT Capitulo (Tema, Seccion+)>
<!ATTLIST Capitulo
materia (XML|Java) "Java"
>
<!ELEMENT Tema (#PCDATA)>
<!ELEMENT Seccion (#PCDATA)>
<!ATTLIST Seccion
apartados CDATA #REQUIRED
dificil (si|no) "no"
>
<!ELEMENT Separacion EMPTY>
<!ELEMENT Copyright (#PCDATA)>
y probarlo con este documento:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE Libro [
<!ENTITY OReillyCopyright SYSTEM "copyright.txt">
]>
<Libro xmlns="http://www.mislibros.com/libros/javaxml"
xmlns:Catalogo="http://www.mislibros.com/catalogo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mislibros.com/libros/javaxml libro.xsd">
<Titulo>Java y XML</Titulo>
<Contenido>
<Capitulo materia="XML">
<Tema>Introducción</Tema>
<Seccion apartados="7">Qué es</Seccion>
<Seccion apartados="3">Cómo se usa</Seccion>
</Capitulo>
<Capitulo materia="XML">
<Tema>Creando XML</Tema>
<Seccion apartados="0">Un documento XML</Seccion>
<Seccion apartados="2">La cabecera</Seccion>
<Seccion apartados="6">El contenido</Seccion>
</Capitulo>
<Capitulo>
<Tema>Analizando XML</Tema>
<Seccion apartados="3">Preparación</Seccion>
<Seccion apartados="3" dificil="true">SAX</Seccion>
<Seccion apartados="9" dificil="true">Manejadores</Seccion>
<Seccion apartados="0">Una forma mejor de cargar el analizador</Seccion>
</Capitulo>
<Separacion/>
<Capitulo materia="Java">
<Tema>JDOM</Tema>
<Seccion apartados="2">Introducción</Seccion>
<Seccion apartados="4" dificil="true">DOM&JDOM</Seccion>
</Capitulo>
</Contenido>
<Copyright>&OReillyCopyright;</Copyright>
</Libro>
Solución
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.mislibros.com/libros/javaxml"
xmlns="http://www.mislibros.com/libros/javaxml"
elementFormDefault="qualified">
<xs:element name="Libro" type="TipoLibro"/>
<xs:complexType name="TipoLibro">
<xs:sequence>
<xs:element name="Titulo" type="xs:string"/>
<xs:element name="Contenido" type="TipoContenido"/>
<xs:element name="Copyright" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TipoContenido">
<xs:sequence maxOccurs="unbounded">
<xs:element name="Capitulo" type="TipoCapitulo" maxOccurs="unbounded"/>
<xs:element name="Separacion" type="TipoVacio" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TipoCapitulo">
<xs:sequence>
<xs:element name="Tema" type="xs:string"/>
<xs:element name="Seccion" type="TipoSeccion" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="materia" type="TipoMateria" default="Java"/>
</xs:complexType>
<xs:complexType name="TipoSeccion">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="apartados" type="xs:nonNegativeInteger" use="required"/>
<xs:attribute name="dificil" type="xs:boolean" default="false"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="TipoMateria">
<xs:restriction base="xs:string">
<xs:enumeration value="Java"/>
<xs:enumeration value="XML"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TipoVacio"/>
</xs:schema>
XSLT
Enunciado
A partir del siguiente documento XML, realizar una hoja de estilo
XSLT que muestre los datos en una tabla, con las siguientes
características: las empresas aparecen ordenadas por el precio de
cotización, los precios supreriores a 75 aparecen en azul y los
inferiores a 25 en rojo, las empresas del índice general aparecen
marcadas con un (*), con una explicación debajo de la tabla. El
título del documento refleja el día y hora de la información.
<?xml version="1.0" ?>
<Bolsa xmlns="http://www.labolsa.com"
dia="5-7-2001"
hora="11:34">
<Empresa indice="general">
<Nombre>General Motors</Nombre>
<Simbolo>GMO</Simbolo>
<Precio>28.875</Precio>
</Empresa>
<Empresa indice="tecno">
<Nombre>Adobe</Nombre>
<Simbolo>ADB</Simbolo>
<Precio>92.250</Precio>
</Empresa>
<Empresa indice="tecno">
<Nombre>Microsoft</Nombre>
<Simbolo>MSF</Simbolo>
<Precio>20.313</Precio>
</Empresa>
<Empresa indice="general">
<Nombre>Coca-Cola</Nombre>
<Simbolo>COC</Simbolo>
<Precio>38.895</Precio>
</Empresa>
<Empresa indice="tecno">
<Nombre>Sun Microsystems</Nombre>
<Simbolo>SUN</Simbolo>
<Precio>45.119</Precio>
</Empresa>
</Bolsa>
Solución
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:Bolsa="http://www.labolsa.com"
version="1.0">
<xsl:template match="Bolsa:Bolsa">
<html>
<head>
<title>La bolsa el <xsl:value-of select="@dia" /> a las
<xsl:value-of select="@hora" /></title>
</head>
<body>
<table border="2" align="center">
<tr>
<th>Símbolo</th>
<th>Nombre</th>
<th>Precio</th>
</tr>
<xsl:for-each select="Bolsa:Empresa">
<xsl:sort select="Bolsa:Precio" order="descending"/>
<tr>
<td>
<xsl:value-of select="Bolsa:Simbolo"/>
</td>
<td>
<xsl:value-of select="Bolsa:Nombre"/>
<xsl:if test="@indice='general'"> (*)</xsl:if>
</td>
<td>
<xsl:choose>
<xsl:when test="Bolsa:Precio > 75">
<font color="blue"><xsl:value-of select="Bolsa:Precio"/></font>
</xsl:when>
<xsl:when test="Bolsa:Precio < 25">
<font color="red"><xsl:value-of select="Bolsa:Precio"/></font>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Bolsa:Precio"/>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
<p align="center">(*) Estas empresas son del índice general</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
SAX
Enunciado
Realizar mediante SAX un programa para el documento del libro. El
programa debe escribir en un fichero los títulos de los capítulos y
un pequeño resumen para cada uno de ellos con el número de
secciones, de apartados totales y de apartados difíciles.
Solución
import java.io.IOException;
import java.io.FileWriter;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.helpers.XMLReaderFactory;
public class EjercicioSAX {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Debe haber un parámetro (el fichero)");
}
else {
String fich = args[0];
System.out.println("Analizando: " + fich + "\n");
try {
XMLReader parser =
XMLReaderFactory.createXMLReader(
"org.apache.xerces.parsers.SAXParser");
ManejadorCaps man = new ManejadorCaps();
parser.setContentHandler(man);
parser.parse(fich);
System.out.println("Fin del análisis. Todo bien\n");
} catch (IOException e) {
System.out.println(e);
} catch (SAXException e) {
System.out.println(e);
}
}
}
}
class ManejadorCaps implements ContentHandler {
private Locator loc;
private FileWriter f;
private boolean extraer;
private int numSecciones;
private int numApartados;
private int numDificiles;
public void setDocumentLocator(Locator l) {
loc = l;
}
public void startDocument() throws SAXException {
try {
numSecciones = 0;
numApartados = 0;
numDificiles = 0;
f = new FileWriter("capitulos.txt");
}
catch (IOException e) {
throw new SAXException ("Problemas al abrir fichero");
}
}
public void endDocument() throws SAXException {
try {
f.close();
}
catch (IOException e) {
throw new SAXException ("Problemas al cerrar fichero");
}
}
public void startElement(String espacio, String nomLocal,
String nomCompleto, Attributes atrs) {
if (nomLocal.equals("Tema")) {
extraer = true;
}
else if (nomCompleto.equals("Seccion")) {
numSecciones++;
numApartados += Integer.parseInt(atrs.getValue(0));
if (atrs.getValue(1).equals("si")) {
numDificiles++;
}
}
}
public void endElement(String espacio, String nomLocal,
String nomCompleto) throws SAXException {
if (nomLocal.equals("Tema")) {
extraer = false;
}
else if (nomLocal.equals("Capitulo")) {
try {
f.write("\t" + numSecciones + " secciones\r\n" +
"\t" + numApartados + " apartados\r\n" +
"\t(" + numDificiles + " difíciles)\r\n");
numSecciones = 0;
numApartados = 0;
numDificiles = 0;
}
catch (IOException e) {
throw new SAXException ("Problemas al escribir en fichero");
}
}
}
public void characters(char[] ch, int comienzo, int fin)
throws SAXException {
try {
if (extraer) {
String tema = new String(ch, comienzo, fin);
f.write(tema + "\r\n");
}
}
catch (IOException e) {
throw new SAXException ("Problemas al escribir en fichero");
}
}
public void processingInstruction(String destino, String datos) {
}
public void startPrefixMapping(String prefijo, String uri) {
}
public void endPrefixMapping(String prefijo) {
}
public void ignorableWhitespace(char[] ch, int comienzo, int fin) {
}
public void skippedEntity(String nombre) {
}
}
DOM
Enunciado
Realizar mediante DOM un programa para el documento del libro. El
programa debe escribir en un fichero los títulos de los capítulos y
un pequeño resumen para cada uno de ellos con el número de
secciones, de apartados totales y de apartados difíciles.
Solución
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import java.io.IOException;
import org.xml.sax.SAXException;
import org.apache.xerces.parsers.DOMParser;
import java.io.FileWriter;
public class EjercicioDOM {
static FileWriter f;
static int numSecciones;
static int numApartados;
static int numDificiles;
public static void procesar(Node nodo) throws IOException {
Element e = (Element)nodo;
String nombre = e.getNodeName();
if (nombre.equals("Libro")) {
f = new FileWriter("capitulosDOM.txt");
NodeList hijos = e.getElementsByTagName("Capitulo");
for (int i=0; i<hijos.getLength(); i++) {
procesar(hijos.item(i));
}
f.close();
}
else if (nombre.equals("Capitulo")) {
procesar(e.getElementsByTagName("Tema").item(0));
NodeList hijos = e.getElementsByTagName("Seccion");
numSecciones = hijos.getLength();
numApartados = 0;
numDificiles = 0;
for (int i=0; i<hijos.getLength(); i++) {
procesar(hijos.item(i));
}
f.write("\tSecciones: " + numSecciones + "\r\n");
f.write("\tApartados: " + numApartados + "\r\n");
f.write("\t(Difíciles: " + numDificiles + ")\r\n");
}
else if (nombre.equals("Tema")) {
f.write(e.getFirstChild().getNodeValue() + "\r\n");
}
else if (nombre.equals("Seccion")) {
numApartados += Integer.parseInt(e.getAttribute("apartados"));
if (e.getAttribute("dificil").equals("si")) {
numDificiles++;
}
}
}
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Debe haber un parámetro (el fichero)");
}
else {
String fich = args[0];
System.out.println("Generando árbol para: " + fich + "\n");
try {
DOMParser parser = new DOMParser();
parser.parse(fich);
Document doc = parser.getDocument();
procesar(doc.getDocumentElement());
}
catch (IOException e) {
System.out.println(e);
}
catch (SAXException e) {
System.out.println(e);
}
}
}
}
DOM (otro)
Enunciado
Realizar mediante DOM un programa a partir de un documento con
las notas detalladas de una serie de alumnos de una clase. El
programa debe imprimir por pantalla la media de cada alumno y la
media total de la clase, así como generar un documento XML con esta
información.
Entrada
<?xml version="1.0"?>
<course>
<teacher id="jp">
<name>John Punin</name>
</teacher>
<student id="js">
<name>John Smith</name>
<hw1>30</hw1>
<hw2>70</hw2>
<project>80</project>
<final>85</final>
</student>
<student id="gl">
<name>George Lucas</name>
<hw1>80</hw1>
<hw2>90</hw2>
<project>100</project>
<final>40</final>
</student>
<student id="lr">
<name>Elizabeth Roberts</name>
<hw1>60</hw1>
<hw2>95</hw2>
<project>50</project>
<final>100</final>
</student>
</course>
Salida
Alumno John Smith = 66.25
Alumno George Lucas = 77.5
Alumno Elizabeth Roberts = 76.25
Media de la clase = 73.333336
<?xml version="1.0" encoding="UTF-8"?>
<Notas Media="73.333336">
<Alumno>
<Nombre>John Smith</Nombre>
<Nota>66.25</Nota>
</Alumno>
<Alumno>
<Nombre>George Lucas</Nombre>
<Nota>77.5</Nota>
</Alumno>
<Alumno>
<Nombre>Elizabeth Roberts</Nombre>
<Nota>76.25</Nota>
</Alumno>
</Notas>
Solución
import org.w3c.dom.*;
import javax.xml.parsers.*;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xml.serialize.*;
import java.io.*;
public class OtroEjDOM {
static float notas[][] = new float[100][5];
static String nombres[] = new String[100];
public static void main(String[] args) {
try {
DocumentBuilder parser;
DocumentBuilderFactory factoria =
DocumentBuilderFactory.newInstance();
parser = factoria.newDocumentBuilder();
Document doc = parser.parse(args[0]);
NodeList studs = doc.getElementsByTagName("student");
for (int i=0; i<studs.getLength(); i++) {
tratarStud((Element) studs.item(i), i);
}
calcularNotas(studs.getLength());
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
private static void tratarStud(Element elemStud, int numStud) {
nombres[numStud] = extraerValor(elemStud, "name");
notas[numStud][0] = Integer.parseInt(extraerValor(elemStud, "hw1"));
notas[numStud][1] = Integer.parseInt(extraerValor(elemStud, "hw2"));
notas[numStud][2] = Integer.parseInt(extraerValor(elemStud, "project"));
notas[numStud][3] = Integer.parseInt(extraerValor(elemStud, "final"));
}
private static String extraerValor(Element elem, String campo) {
Element subElem = (Element) elem.getElementsByTagName(campo).item(0);
return subElem.getFirstChild().getNodeValue();
}
private static void calcularNotas(int numStuds) {
float media = 0;
int i = 0, j = 0;
System.out.println();
for(i = 0; i < numStuds ; i++) {
float total = 0;
for(j = 0; j < 4; j++) {
total += notas[i][j];
}
notas[i][4] = total/4;
media += notas[i][4];
System.out.println("Alumno " + nombres[i] + " = " + notas[i][4]);
}
media /= numStuds;
System.out.println("Media de la clase = " + media);
System.out.println();
try {
Document doc= new DocumentImpl();
Element raiz = doc.createElement("Notas");
raiz.setAttribute("Media", String.valueOf(media));
for(i = 0; i < numStuds ; i++) {
Element alumno = doc.createElement("Alumno");
Element nombre = doc.createElement("Nombre");
nombre.appendChild(doc.createTextNode(nombres[i]));
alumno.appendChild(nombre);
Element nota = doc.createElement("Nota");
nota.appendChild(doc.createTextNode(String.valueOf(notas[i][4])));
alumno.appendChild(nota);
raiz.appendChild(alumno);
}
doc.appendChild(raiz);
OutputFormat formato = new OutputFormat(doc, "UTF-8", true);
StringWriter s = new StringWriter();
XMLSerializer ser = new XMLSerializer(s, formato);
ser.serialize(doc);
System.out.println(s.toString());
FileWriter f = new FileWriter("notas.xml");
ser = new XMLSerializer(f, formato);
ser.serialize(doc);
} catch (IOException e) {
System.out.println(e);
}
}
}