![]() |
Curso JAVA |
|
www.bit.es - Calendario de cursos - Solicitud de información |
Curso
Java
Curso Analista Programador entorno
Java
Objetivos de la Unidad:
1.- Tipos de aplicaciones JAVA
Pueden
distinguirse 4 tipos:
· Como aplicación tipo consola (entrada/salida standard modo
texto)
· Como aplicación tipo ventanas (Windows, X-Windows, Mac...)
· Como Applet incrustado en un navegador Web
· Como Servlet o conjunto de Servlets (ver Unidad 8)
· Como Midlet (Java Microedition - J2ME)
Ejecución
como aplicación tipo consola
· Al menos una clase deberá tener un método main() que será
el punto de arranque.
· La clase java.lang.System provee de dos objetos in y out que
corresponden a la entrada-salida standard.
· Ejemplo mínimo:
//
HolaMundo.java
class HolaMundo
{
public static void
main(String [] args)
{
System.out.println("Hola
mundo");
}
}
Los servlets
podrían entrar en esta categoría:
import
javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HolaServlet extends HttpServlet
{
public void service (HttpServletRequest req,
HttpServletResponse res) throws
ServletException,
IOException
{
PrintWriter p = res.getWriter();
res.setContentType("text/html");
p.println("<html><body>");
p.println("<h1>Hola
mundo</h1>");
p.println("</body></html>");
p.close();
}
}
Para probar el servlet hay
que ir a un navegador y pedir la siguiente URL:
http://[dirección ip]:[port]/servlet/HolaServlet
Si arrancamos el servidor y el navegador en la misma máquina hay 3 alternativas
más (suponiendo que arranca por el port 8080):
http://localhost:8080/servlet/HolaServlet
http://127.0.0.1:8080/servlet/HolaServlet
http://[nombre máquina windows]:8080/servlet/HolaServlet
Ejecución
como aplicación tipo ventanas
· Hay que gestionar el evento de cerrar la aplicación
//
MiVentana.java
import java.awt.*;
public class MiVentana extends Frame
{
public static void main(String args[])
{
MiVentana f = new
MiVentana("Ventana");
}
public MiVentana( String s )
{
// llama al constructor de la
clase base
super( s );
Label a = new Label(
"Hola Mundo." );
add( "North", a );
resize(300, 300);
show();
}
public boolean handleEvent( Event e )
{
if ( e.id ==
Event.WINDOW_DESTROY )
{
hide();
// esconde la ventana
dispose();
// libera recursos
return
true;
}
return
super.handleEvent( e );
}
}
Ejecución
como aplicación tipo Applet (Un
ejemplo real de applet)
· La clase MiApplet deriva de Applet
//
MiApplet.java
import java.applet.Applet;
import java.awt.Graphics;
public class MiApplet extends Applet
{
public void paint( Graphics g )
{
g.drawString(
"Hola Mundo.", 25, 25 );
}
}
Un applet se integra dentro de una página HTML como sigue:
<html>
<head>
<title>Welcome</title>
</head>
<body>
<applet code=MiApplet.class width=200
height=200></applet>
</body>
</html>
Centrar
una ventana
Podemos
añadir la función centra() a nuestra ventana y llamarla antes de mostrarla:
public void centra()
{
int anchoPantalla =
getToolkit().getScreenSize().width;
int altoPantalla =
getToolkit().getScreenSize().height;
int anchoVentana = getSize().width;
int altoVentana = getSize().height;
setLocation( (anchoPantalla - anchoVentana) / 2,
(altoPantalla - altoVentana) / 2);
}
La versión
Foundation de JBuilder no incorpora el asistente para crear Dialog. Para poder
ser editado con el IDE un Dialog debe incorporar un panel según la siguiente
plantilla:
import java.awt.*;
import java.awt.event.*;
public class MiDlg extends Dialog
{
Panel dlgPanel = new Panel();
public MiDlg(Frame parent, String tit)
{
super(parent, tit);
jbInit();
add(dlgPanel);
}
private void jbInit()
{
dlgPanel.setLayout(null);
}
}
En demodlg.zip
se muestra
cómo manipular un helper con un diálogo activado desde un Frame.
Aplicación J2ME
Java diseñado para pequeños dispositivos como teléfonos móviles ó PDAs.
También disponible para PocketPC (http://www.comp.lancs.ac.uk/computing/users/fittond/ppcjava.htm)
import javax.microedition.lcdui.*; import javax.microedition.midlet.*;
public class HolaMidlet extends MIDlet implements CommandListener {
private Form mainScreen; private Display myDisplay; private Command cmExit;
public HolaMidlet() {
myDisplay = Display.getDisplay(this);
mainScreen = new Form("HolaMundo");
StringItem strItem = new StringItem("Hola", "Hola Mundo");
mainScreen.append(strItem);
cmExit = new Command("Exit", Command.SCREEN, 1);
mainScreen.addCommand(cmExit);
mainScreen.setCommandListener(this);
}
public void startApp() throws MIDletStateChangeException {
myDisplay.setCurrent(mainScreen);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable s)
{
if (c == cmExit)
{
destroyApp(false);
notifyDestroyed();
}
}
}
2.-
Applets de JAVA
Para
empezar como lectura introductoria sobre applets puede empezarse
por el tutorial en castellano de Agustín Froufe en http://www.fie.us.es/info/internet/JAVA/Cap2/holamapp.html
En particular la cuestión del ciclo de vida de los applets está expuesta en el mismo tutorial en http://www.fie.us.es/info/internet/JAVA/Cap2/metodv.html
Ya en inglés sobre applets puede consultarse la versión del
tutorial de Sun en http://java.sun.com/docs/books/tutorial/applet/overview/index.html
En http://www.galeon.com/juegosjava/menu.html se encuentra una buena colección de juegos interactivos basados en applets de Java.
En relación a la optimización de los tiempos de carga y respuesta de los applets se pueden consultar los siguientes artículos:
En
cuanto a applets y seguridad (certificados):
Un
applet puede abrir un fichero en el servidor de donde ha sido
descargado y leer datos de él. Para ello hay que añadir las
siguientes líneas de código:
URL url = new URL(getDocumentBase(), "fichero.txt");
InputStream in = url.openStream();
Para
implementar una solución cliente/servidor el applet deberá
comunicarse con un servidor. Una posibilidad es usar RMI. Esta
opción, si bien puede ser óptima en un ámbito tipo red de
área local presenta ciertas limitaciones en entornos tipo
Internet en que los proxies y firewalls pueden presentar
problemas de conexión. La otra posibilidad es comunicar el
applet con un servlet vía HTTP. Las formas de cómo realizarlo
se describen en el artículo http://www.gamelan.com/journal/techworkshop/012600_appserv.html
Un applet puede ser descargado y ejecutarse autónomamente, sin
conexión con otro proceso pero realizando ciertas
funcionalidades. En el ejemplo siguiente se muestra como provocar
una llamada a una página web en función de un click del mouse.
El ejemplo puede ampliarse carruseles dinámicos de imágenes o a
mapas.
3.-
Ejemplo de Marquee
import
java.awt.*;
import
java.applet.*;
import
java.net.*;
public
class Marquee extends Applet implements Runnable
{
String text;
Font font = new Font("Helvetica", 1, 24);
Color color = new Color(94, 60, 215);
int xpos = 0;
Thread killme = null;
public void init()
{
text = getParameter("TEXT");
}
public void paint(Graphics g)
{
setBackground(new
Color(196, 196, 210));
g.setFont(font);
g.setColor(color);
g.drawString(text, xpos, 25);
}
public void start()
{
if(killme == null)
{
killme = new Thread(this);
killme.start();
}
}
public void setText(String s)
{
text = s;
}
public void setCoord(int x)
{
xpos = x;
}
public void setCoord()
{
xpos = xpos-5;
if(xpos < -120)
xpos = size().width;
}
public void run()
{
while(killme != null)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e){}
setCoord();
repaint();
}
}
public void stop()
{
killme = null;
}
public
boolean mouseDown(Event e, int x, int y)
{
try
{
URL u = new
URL("http://www.yahoo.com");
getAppletContext().showDocument(u);
}
catch (Exception ex)
{
System.out.println(ex);
// es enviado a la Java console
}
return false;
}
}
HTML
asociado ilustrando la interacción con JavaScript:
<HTML>
<BODY>
<H2>Interacción de JavaScript con
Java</H2>
<FORM>
<APPLET
CODEBASE = "."
CODE = "Marquee.class"
NAME = "TestApplet"
WIDTH = 240
HEIGHT = 35
HSPACE = 0
VSPACE = 0
ALIGN = middle
>
<PARAM NAME="TEXT" VALUE="Hola">
</APPLET>
<P>
<INPUT TYPE="BUTTON" VALUE="Poner coordenada a
30" onClick="coord(30);"><BR>
<HR>
<INPUT TYPE="TEXT" VALUE="Adiós"
NAME="TEXTO" SIZE="25">
<INPUT TYPE="BUTTON" VALUE="Poner texto"
onClick="text(window.document.forms[0].elements['TEXTO'].value);"><BR>
</FORM>
</BODY>
<SCRIPT>
function coord(x)
{
window.document.TestApplet.setCoord(x);
}
function text(s)
{
window.document.TestApplet.setText(s);
}
</SCRIPT>
</HTML>
4.- Introspección y Java reflection
Uno de
los puntales de los JavaBeans son los mecanismos de
introspección:
(Nota: Para que el ejemplo funcione es preferible declarar public
algunos campos de la clase Rectangulo ya utilizada en la Ud 3)
import
java.lang.reflect.*;
public class PruebasReflection
{
public
static void main(String[] args) throws Exception
{
Rectangulo r = new Rectangulo(1, 2, 3,
4);
Class clase = r.getClass(); // También valdría
Class clase = Rectangulo.class;
System.out.println("r es de la clase
" + clase.getName());
// introspección de los campos públicos
// getDeclaredFieds() devuelve los
declarados excluyendo los heredados
Field[] campos = clase.getFields();
for (int i = 0; i < campos.length;
i++)
{
Class tipoCampo =
campos[i].getType();
System.out.println(campos[i].getName()
+ " es del tipo " + tipoCampo.getName());
}
// introspección de los métodos
públicos
// getDeclaredMethods() devuelve los
declarados excluyendo los heredados
Method[] metodos = clase.getMethods();
for (int i = 0; i < metodos.length;
i++)
{
Class tipoValorRetorno =
metodos[i].getReturnType();
Class[] tiposParametros =
metodos[i].getParameterTypes();
System.out.println("Método:
" + metodos[i].getName());
System.out.println("
Retorno: " + metodos[i].getReturnType().getName());
for (int j = 0; j <
tiposParametros.length; j++)
{
System.out.println("
Parámetro: " + tiposParametros[j].getName());
}
}
// ejemplo del CallByName del método
setX(int valor)
Class[] tiposParams = new Class[1];
tiposParams[0] = Integer.TYPE; //
Interesante ver cómo referenciar a los tipos primitivos
Method metodoSetBase =
clase.getMethod("setBase", tiposParams);
Object[] params = new Object[1];
params[0] = new Integer(8);
metodoSetBase.invoke(r, params);
// comprobación:
System.out.println("Nueva base:
" + r.getBase());
// CallByName de area
tiposParams = new Class[0]; // truco para
indicar que no recibe parámetros
Method metodoArea =
clase.getMethod("area", tiposParams);
params = new Object[0];
Double area = (Double)
metodoArea.invoke(r, params);
System.out.println("Nueva área:
" + area.doubleValue());
}
}
A continuación se dispone de una clase Rectangulo reducida en caso de no tener a mano la de la Ud3
public class Rectangulo
{
private int base;
private int altura;
public int x;
protected int y;
public Rectangulo(int x, int y, int base, int altura)
{
this.x = x;
this.y = y;
setBase(base);
setAltura(altura);
}
public void setBase(int valor)
{
base = valor;
}
public int getBase()
{
return base;
}
public void setAltura(int valor)
{
altura = valor;
}
public int getAltura()
{
return altura;
}
public double area()
{
return base * altura;
}
}
A continuación se muestra un ejemplo curioso. Se trata de un programa que crea un fichero ASCII de código fuente denominado Holax.java, lo compila generando el fichero Holax.class, a continuación carga la clase Holax con el método forName() y finalmente crea una instancia de la clase Holax con newInstance(). Debido a que el constructor de la clase Holax imprime "Holax" se comprueba que realmente dicho constructor se ejecuta.
import
java.io.*;
public class Autogeneracion
{
public static void main(String[] args) throws
Exception
{
FileOutputStream f = new
FileOutputStream("Holax.java");
PrintWriter p = new PrintWriter(f);
p.println("public class
Holax");
p.println("{");
p.println(" public Holax()");
p.println(" {");
p.println("
System.out.println(\"Holax\");");
p.println(" }");
p.println("}");
p.close();
String params[] = new String[1];
params[0] = "Holax.java";
// Este paquete viene con el JDK pero no
está documentado.
// En realidad el comando
"javac" es equivalente a "java
sun.tools.javac.Main"
new sun.tools.javac.Main(System.out,
"javac").compile(params);
Class clase =
Class.forName("Holax");
clase.newInstance();
}
}
5.- JavaBeans
Los
JavaBeans constituyen el sistema de software basado en
componentes de la plataforma Java. Existe un mercado de
componentes de software JavaBeans. Actualmente la mayoría de
proveedores de componentes ofrecen tanto la versión ActiveX como
la JavaBean. Un directorio de referencia global sobre este
mercado está en http://www.flashline.com y para el
mercado español está http://www.ramblainf.com
Un JavaBean es en terminología UML un estereotipo. No se define
como una subclase de una clase o un interface sino que responde a
un cierto modo de implementar una clase.
Las reglas básicas son:
Con lo dicho anteriromente la propiedad ya aparece en la ventana de propiedades y es utilizable lo que nos valdrá en la mayoría de los casos
Adicionalmente puede aumentarse el nivel de personalización de los JavaBeans que puede realizar a dos niveles:
El otro aspecto personalizable son los eventos. Se adjunta un ejemplo completo en que se crea un Bean a partir de la clase java.awt.List y a la que se añade el evento TopeEvent que se dispara al seleccionar al primero o últmo elemento. El método getDonde() indicará si estamos al principio o al fin:
/**************************************************************
* Ejemplo completo de JavaBean con custom event
**************************************************************/
package PruebaBeanEvent;
import java.util.*;
public class TopeEvent extends EventObject
{
private String donde;
public TopeEvent(Object origen)
{
super(origen);
}
public TopeEvent(Object origen, String donde)
{
super(origen);
this.donde = donde;
}
public String getDonde()
{
return donde;
}
}
///////////////////////////////////////////////////////////////
package PruebaBeanEvent;
import java.util.*;
public interface TopeEventListener extends EventListener
{
public void topeAlcanzado(TopeEvent e);
}
///////////////////////////////////////////////////////////////
package PruebaBeanEvent;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class Lista extends List
{
private transient Vector topeEventListeners;
public Lista()
{
super();
try
{
jbInit();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
this.setFont(new
Font("Courier", 0, 12));
this.setSize(new Dimension(151, 177));
this.addItemListener(new
java.awt.event.ItemListener()
{
public void
itemStateChanged(ItemEvent e)
{
this_itemStateChanged(e);
}
});
}
void this_itemStateChanged(ItemEvent e)
{
int item = getSelectedIndex();
int n = getItemCount();
if (item == 0)
{
fireTopeEvent("Inicio");
}
if (item == n - 1)
{
fireTopeEvent("Fin");
}
}
public synchronized void
addTopeEventListener(TopeEventListener el)
{
if (topeEventListeners == null)
topeEventListeners = new
Vector();
topeEventListeners.addElement(el);
}
public synchronized void
removeTopeEventListener(TopeEventListener el)
{
if (topeEventListeners != null)
topeEventListeners.removeElement(el);
}
private void fireTopeEvent(String donde)
{
if (topeEventListeners != null)
{
Vector v =
(Vector)topeEventListeners.clone();
TopeEvent e = new
TopeEvent(this, donde);
for (int i = 0; i <
v.size(); i++)
{
TopeEventListener
el;
el =
(TopeEventListener) v.elementAt(i);
el.topeAlcanzado(e);
}
}
}
}
/**************************************************************
* Frame de pruebas
**************************************************************/
package PruebaBeanEvent;
import java.awt.*;
import java.awt.event.*;
import PruebaBeanEvent.*;
public class FramePrueba extends Frame
{
Lista lista1 = new Lista();
Button button1 = new Button();
public FramePrueba()
{
try
{
jbInit();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
FramePrueba framePrueba1 = new
FramePrueba();
framePrueba1.setVisible(true);
}
private void jbInit() throws Exception
{
this.setBackground(new Color(192, 192,
213));
this.setSize(new Dimension(372, 274));
this.addWindowListener(new
java.awt.event.WindowAdapter()
{
public void
windowClosing(WindowEvent e)
{
this_windowClosing(e);
}
});
lista1.setBounds(new Rectangle(30, 39,
310, 163));
lista1.addTopeEventListener(new
PruebaBeanEvent.TopeEventListener()
{
public void
topeAlcanzado(TopeEvent e)
{
lista1_topeAlcanzado(e);
}
});
button1.setBounds(new Rectangle(154, 226,
68, 28));
button1.setLabel("Omplir");
button1.addActionListener(new
java.awt.event.ActionListener()
{
public void
actionPerformed(ActionEvent e)
{
button1_actionPerformed(e);
}
});
this.setLayout(null);
this.add(lista1, null);
this.add(button1, null);
int anchoPantalla =
getToolkit().getScreenSize().width;
int altoPantalla =
getToolkit().getScreenSize().height;
int anchoVentana = getSize().width;
int altoVentana = getSize().height;
setLocation( (anchoPantalla -
anchoVentana) / 2, (altoPantalla - altoVentana) / 2);
}
void button1_actionPerformed(ActionEvent e)
{
lista1.add("Sol |Domingo");
lista1.add("Luna |Lunes");
lista1.add("Mercurio
|Miércoles");
lista1.add("Venus |Viernes");
lista1.add("Tierra |");
lista1.add("Marte |Martes");
lista1.add("Jupiter |Jueves");
lista1.add("Saturno |Sábado");
lista1.add("Urano |");
lista1.add("Neptuno |");
lista1.add("Plutón |");
}
void this_windowClosing(WindowEvent e)
{
System.exit(0);
}
void lista1_topeAlcanzado(TopeEvent e)
{
System.out.println("Evento al "
+ e.getDonde());
}
}
Existe en Java el
concepto de propiedades ligadas y funciona de forma similar al
ejemplo anterior. La idea es que cuando varía una de ellas se
dispara el evento PropertyChangeEvent que es enviado a todos los
listeners registrados. Luego, como de cualquier EventObject (superclase de PropertyChangeEvent) se puede obtener con getSource() el objeto emisor y
discriminar la acción a tomar.
El bean con propiedades ligadas deberá cumplir los siguientes
requisitos:
1) import java.beans.*;
2) Referenciar un objeto del tipo PropertyChangeSupport como atributo del bean:
private PropertyChangeSupport gestorLigadas = new PropertyChangeSupport(this);
3) Incluir sendos métodos para dar de alta y de baja los PropertyChangeListeners:
public void
addPropertyChangeListener (PropertyChangeListener p)
{
gestorLigadas.addPropertyChangeListener(p);
}
public void
removePropertyChangeListener (PropertyChangeListener p)
{
gestorLigadas.removePropertyChangeListener(p);
}
4) Modificar los "setters" de las propiedades que queramos que disparen el evento PropertyChangeEvent en los listeners registrados:
public final
void set<propiedad> (<Tipo> valor)
{
...
gestorLigadas.firePropertyChange("<nombre_propiedad>",
<valor_anterior>, valor);
...
}
Los IDE suelen
incorporar asistentes para facilitar la personalización de los
Beans. Para el caso de Visual Age for Java se puede encontrar
interesante información sobre cómo crear custom events en
http://www-4.ibm.com/software/developer/education/cdtut4java/vptut2_cd_1.htm
El libro "Processing XML in Java" se puede consultar on-line en http://www.ibiblio.org/xml/books/xmljava/chapters y es una buena referencia bibliográfica. En castellano se puede consultar un gran tutorial en http://programacion.com/tutorial/joa_xml. Un buen punto de referencia sobre estándares sectoriales se puede encontrar en http://www.xml.org/xml/industry_industrysectors.jsp
IBM dispone de parsers XML en Java de reconocido prestigio. IBM Japón es líder en este ámbito. Sun también provee un estándar para parsers XML denominado JAXP y la implantación denominada Xerces. (incluido en Tomcat y para JDK >= 1.4 está disponible en http://java.sun.com/xml/xml_jaxp.html)
Estándares XML:
XML (y DTDs): http://www.w3.org/TR/REC-xml
XML Namespaces: http://www.w3.org/TR/REC-xml-names
XSLT: http://www.w3.org/TR/xslt
Associating Stylesheets with XML: http://www.w3.org/TR/xml-stylesheet
XPath: http://www.w3.org/TR/xpath
(trad. http://www.sidar.org/recur/desdi/traduc/es/xml/xpath.html
)
CSS (Level 1): http://www.w3.org/TR/REC-CSS1
XML Schema: http://www.w3.org/TR/xmlschema-0
FOP: http://www.renderx.com/Tests/doc/html/tutorial.html
FOP + XSLT: http://www.antennahouse.com/XSLsample/XSLsample.htm
Microsoft ofrece unos módulos para que el Internet Explorer valide muestre el
código resultante de las XSLT en http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/htm/xslt_starter_7cf8.asp
La compatibilidad del MS IExplorer con los estánadares se trata en http://www.albany.edu/~gilmr/xclass/c5/processors/xalanVsIE.html
Asimismo BEA nos ofrece de un editor XML en http://dev2dev.bea.com/resourcelibrary/utilitiestools/xml.jsp?highlight=utilitiestools
Dentro de las herramientas de edición de XSLT es interesante la Sonic Stylus
Studio (se recomienda ver los videos de demo) http://www.sonicsoftware.com/products/additional_software/stylus_studio/index.ssp
De XSLT hay un buen tutorial en http://www.zvon.org/xxl/XSLTutorial/Books/Book1/ y de XPATH otro en http://www.zvon.org/xxl/XPathTutorial/Output_spa/example1.html
Son interesantes los ejemplos en que se ve paso a paso cómo se ejecuta la XSLT http://www.zvon.org/xxl/XSLTracer/Output/examplelist.html
Un tutorial de XML-Schema se puede encontrar en
http://www.zvon.org/xxl/XMLSchemaTutorial/Output/series.html
Tools de command line (JAXP):
import java.io.*;
import java.net.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class validaxml
{
public static void main(String[] args) throws Exception
{
Document doc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(args[0]);
System.out.println(args[0] + " Ok");
}
}
Para arreglar un XML y que se vea bien podemos utilizar:
import java.io.*; import java.net.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import org.w3c.dom.*;
public class arreglaxml
{
public static void main(String[] args) throws Exception
{
String ficheroEntrada = "entrada.xml";
String ficheroSalida = "salida.xml";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(ficheroEntrada);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
// transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//BIT//APEJ//ES");
// transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.miservidor.com/fichero.dtd");
// No hace falta con JDK >= 1.4
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
File newXML = new File(ficheroSalida);
FileOutputStream os = new FileOutputStream(newXML);
StreamResult result = new StreamResult(os);
transformer.transform(source, result);
os.close();
System.out.println("Fin");
}
}
Para validar con DTDs por línea de comando se puede utilizar:
import java.io.*;
import java.net.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
public class validadtd
{
public static void main(String[] args) throws Exception
{
Document doc = null;
File f = new File("");
String fichero = "file:///" + f.getAbsolutePath() + "/" + args[0];
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource entrada = new InputSource(fichero);
System.out.println("DTD detectada = " + entrada.getSystemId());
doc = builder.parse(args[0]);
System.out.println(args[0] + " Ok");
}
}
Para validar schemas
disponemos de Xerces que lo soprorta. Se puede obtener el código fuente de un
validador en http://www.masda.vxu.se/~jonasl/xmljava/lab1.html
En JAXP es:
import java.io.*;
import java.net.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class validaschema
{
static final String JAXP_SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
static final String W3C_XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema";
static final String JAXP_SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
public static void main(String[] args) throws Exception
{
Document doc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
factory.setNamespaceAware(true);
factory.setValidating(true);
factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
factory.setAttribute(JAXP_SCHEMA_SOURCE, new File(args[1]));
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(args[0]);
System.out.println(args[0] + " Ok");
}
}
Hay alternativas a los XML
Schema como Relax NG. Es interesante el artículo http://www.webreference.com/xml/column59/
. La especificación de Relax NG se puede consultar en http://www.oasis-open.org/committees/relax-ng/spec-20011203.html
y hay herramientas que lo soportan como Jing http://www.thaiopensource.com/relaxng/jing.html
DOM significa Document Object Model. Se trata de un conjunto de APIs XML
estándar para ser implementadas en diversos lenguajes. Hay implementaciones en
Java, C++, .net, etc.
import java.io.*;
import org.apache.xerces.parsers.*;
import org.apache.xerces.dom.*;
import org.apache.xml.serialize.*;
import org.w3c.dom.*;
public class PruebaXML
{
public static void main(String[] args) throws
Exception
{
// Interfaz DOM
Document doc = new DocumentImpl();
Text text;
Element pedido = (Element)
doc.createElement ("pedido");
pedido.setAttribute ("ancho",
"45");
doc.appendChild (pedido);
text = doc.createTextNode ("Etiqueta interna");
pedido.appendChild (text);
Element clienteId = (Element)
doc.createElement ("clienteId");
pedido.appendChild (clienteId);
text = doc.createTextNode
("0123A");
clienteId.appendChild (text);
Comment com = doc.createComment("Ejemplo de XML. Bit SA");
pedido.appendChild(com);
Element items = (Element)
doc.createElement ("item");
pedido.appendChild (items);
text = doc.createTextNode
("100");
items.appendChild (text);
items = (Element) doc.createElement
("item");
pedido.appendChild (items);
text = doc.createTextNode
("200");
items.appendChild (text);
System.out.println("Salida
XML");
// con el parser antiguo de Sun era así de simple:
// doc.write (out);
//Con Xerces es:
OutputFormat format = new OutputFormat(
doc ); //Serialize DOM
format.setEncoding("ISO-8859-1"); // OJO: si no se pone utiliza UTF-8
XMLSerializer serial = new XMLSerializer(System.out, format);
serial.asDOMSerializer();
serial.serialize(doc.getDocumentElement());
// si en lugar de System.out utilizamos un FileOutputStream recordar cerrarlo: f.close();
System.out.println("----------------------------");
System.out.println("Listado del
arbol:\n");
NodeList nl = doc.getChildNodes();
System.out.println("\nPrimer nivel:");
for (int i = 0; i < nl.getLength();
i++)
{
System.out.println(nl.item(i).getNodeName());
}
nl =
doc.getElementsByTagName("*");
System.out.println("\nTodos los niveles:");
for (int i = 0; i < nl.getLength();
i++)
{
Node nod = nl.item(i);
System.out.println(nod.getNodeName() + ":
" + nod.getFirstChild().getNodeValue());
}
}
}
IBM, Sun, Oracle y Microsoft
(entre otras empresas) están apostando fuerte en el campo de XML. En particular
Oracle ofrece soluciones Java con soporte para DTDs y XSLT de las que se habla
en http://otn.oracle.com/tech/xml/info/htdocs/otnwp/about_xml.htm
El ejemplo anterior con el parser de Oracle (disponible gratuitamente previo
registro en http://otn.oracle.com/software/content.html)
quedaría como
sigue:
import java.io.*;
import oracle.xml.parser.*;
import oracle.xml.parser.v2.*;
import org.w3c.dom.*;
public class PruebaXML
{
public static void main(String[] args) throws Exception
{
// Interfaz DOM
Document doc = new XMLDocument();
Text text;
Element pedido =
(Element) doc.createElement ("pedido");
pedido.setAttribute ("ancho", "45");
doc.appendChild (pedido);
text = doc.createTextNode ("Etiqueta interna");
pedido.appendChild (text);
Element clienteId =
(Element) doc.createElement ("clienteId");
pedido.appendChild (clienteId);
text = doc.createTextNode ("0123A");
clienteId.appendChild (text);
Comment com = doc.createComment("Ejemplo de XML. Bit SA");
pedido.appendChild(com);
Element items = (Element) doc.createElement ("item");
pedido.appendChild (items);
text = doc.createTextNode ("100");
items.appendChild (text);
items =
(Element) doc.createElement ("item");
pedido.appendChild (items);
text = doc.createTextNode ("200");
items.appendChild (text);
System.out.println("Salida XML");
((XMLDocument)doc).setEncoding("ISO-8859-1"); // OJO: si no se pone
podría salir UTF-8
((XMLDocument)doc).print(System.out);
System.out.flush();
System.out.println("----------------------------");
System.out.println("Listado del arbol:\n");
NodeList nl = doc.getChildNodes();
System.out.println("Primer nivel:");
for (int i = 0; i < nl.getLength(); i++)
System.out.println(nl.item(i).getNodeName());
nl = doc.getElementsByTagName("*");
System.out.println("\nTodos los niveles:");
for (int i = 0; i < nl.getLength(); i++)
{
Node nod = nl.item(i);
System.out.println(nod.getNodeName() + ":
" + nod.getFirstChild().getNodeValue());
}
}
}
En el siguiente ejemplo se ve cómo descargar una página XML de Internet y cómo obtener un objeto DOM asociado y listar su contenido:
import java.io.*; import java.net.*; import org.apache.xerces.parsers.*; import org.apache.xerces.dom.*; import org.apache.xml.serialize.*; import org.w3c.dom.*;
public class PruebaXML2
{
public static void main(String[] args) throws Exception
{
// con Oracle es (acordarse de los imports - ver ej. anterior)
//// URL url = new URL("file:///C:\\Windows\\Escritorio\\pedido.xml"); // para fichero local
//URL url = new URL("http://www.bit-net.org/java/pedido.xml");
//URLConnection conn = url.openConnection();
//InputStream in = conn.getInputStream();
//DOMParser dp = new DOMParser();
//dp.setPreserveWhitespace(true);
//dp.parse(in);
//Document doc = dp.getDocument();
// String fichero = "file:///C:/Windows/Escritorio/pedido.xml";
String fichero = "http://www.bit-net.org/java/pedido.xml";
DOMParser dp = new DOMParser();
dp.setIncludeIgnorableWhitespace(true);
dp.parse(fichero);
Document doc = dp.getDocument();
System.out.println("----------------------------");
System.out.println("Listado del arbol:\n");
NodeList nl = doc.getChildNodes();
System.out.println("Primer nivel:");
for (int i = 0; i < nl.getLength(); i++)
System.out.println(nl.item(i).getNodeName());
nl = doc.getElementsByTagName("*");
System.out.println("\nTodos los niveles:");
for (int i = 0; i < nl.getLength(); i++)
{
Node nod = nl.item(i);
System.out.println(nod.getNodeName() + ": " + nod.getFirstChild().getNodeValue());
}
}
}
Con JAXP queda:
import java.io.*; import java.net.*; import javax.xml.parsers.*; import org.w3c.dom.*;
public class PruebaXML3
{
public static void main(String[] args) throws Exception
{
// String fichero = "file:///C:/Windows/Escritorio/pedido.xml";
String fichero = "http://www.bit-net.org/java/pedido.xml";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// factory.setValidating(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(fichero);
System.out.println("----------------------------");
System.out.println("Listado del arbol:\n");
NodeList nl = doc.getChildNodes();
System.out.println("Primer nivel:");
for (int i = 0; i < nl.getLength(); i++)
System.out.println(nl.item(i).getNodeName());
nl = doc.getElementsByTagName("*");
System.out.println("\nTodos los niveles:");
for (int i = 0; i < nl.getLength(); i++)
{
Node nod = nl.item(i);
System.out.println(nod.getNodeName() + ": " + nod.getFirstChild().getNodeValue());
}
}
}
Un aspecto de creciente interés es
la generación de capa de presentación mediante la interacción de documentos
XML y XSL. Para ilustrarlo disponemos de un ejemplo xmlpruebas.zip
basado en las librerías de Oracle.
Para transformaciones XSLT puede tomarse el siguiente código
como ejemplo. Está muy de actualidad transformar canales RSS de noticias. La
especificación RSS está en
http://blogs.law.harvard.edu/tech/rss
y publicaciones on-line RSS son numerosísimas. Para ello falta una XSLT para
RSS. Una básica se puede obtener del artículo
http://www-106.ibm.com/developerworks/xml/library/x-tiphdln.html
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class xslt
{
public static void main(String[] args) throws Exception
{
genXSLT(args[0], args[1], args[2]);
}
public static void genXSLT(String xmlFile, String xslFile, String outFile) throws Exception
{
OutputStream out = new FileOutputStream(outFile);
TransformerFactory tFactory = TransformerFactory.newInstance();
StreamSource sc = new StreamSource(xslFile);
Transformer transformer = tFactory.newTransformer(sc);
FileInputStream fin = new FileInputStream(xmlFile);
StreamSource scfin = new StreamSource(fin);
// scfin.setSystemId("xxxxx.dtd");
// System.out.println("System ID = " + scfin.getSystemId());
transformer.transform(scfin, new StreamResult(out));
out.close();
}
}
Y para transformaciones PDF con Fop (y con pequeñas variaciones a texto o AWT) puede utilizarse el siguiente código de referencia:
import java.io.*;
import org.apache.fop.apps.*;
import org.xml.sax.XMLReader;
import org.w3c.dom.*;
public class pdf
{
public static void main(String[] args) throws Exception
{
genPDF(args[0], args[1], args[2]);
}
public static void genPDF(File xmlFile, File xslFile, File outFile) throws Exception
{
Driver driver = new Driver();
driver.setRenderer(Driver.RENDER_PDF); // RENDER_TXT, RENDER_AWT, RENDER_SVG, RENDER_PCL etc.
InputHandler inputHandler = new XSLTInputHandler(xmlFile, xslFile);
XMLReader parser = inputHandler.getParser();
FileOutputStream fout = new FileOutputStream(outFile);
driver.setOutputStream(fout);
driver.render(parser, inputHandler.getInputSource());
driver.reset();
fout.close();
}
}
Información de las API (SAX y DOM ya integrado en el JDK 1.4):
http://java.sun.com/j2se/1.4/docs/api/index.html
Es habitual encapsular las APIs de XML con un controlador propio. Un
ejemplo de ello puede verse en
XmlCtl.java
XML es la base de los WebServices. Un descriptor WSDL
(spec: www.w3.org/TR/wsdl) que significa Web Service Definition Language es un
XML que incluye información de tipos de datos según XML-Schema (tutorial: www.zvon.org/xxl/XMLSchemaTutorial) y
spec: www.w3.org/XML/Schema), así como las definiciones SOAP
(spec: www.w3.org/TR/soap) de los WebServices. Puede verse en ejemplo en
webservices.aeroflot.aero/flightstatus.wsdl en el que
la compañía rusa Aeroflot ofrece servicios de información sobre vuelos y aeropuertos.
Idea clave: A partir del WSDL se las herramientas de desarrollo generan automáticamente código en su
propio lenguaje permitiendo interoperabilidad remota entre platadormas y lenguajes con alto nivel de transparencia.
Dada la complejidad de todo ello la WS-I (Web Services Interoperability Organization www.ws-i.org) es una organización
que vela por la compatibilidad entre los Web Services.
Unidad anterior - Unidad siguiente