Apuntes de XML

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&amp;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 &gt; 75">
              <font color="blue"><xsl:value-of select="Bolsa:Precio"/></font>
            </xsl:when>
            <xsl:when test="Bolsa:Precio &lt; 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);
    } 
  }
}

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP