[Métodos] Conocer IP donde ejecutamos Java


Para conocer nuestra ip local debemos recurrir a la clase java.net.InetAddress

Esta clase representa una dirección de protocolo de internet(IP) o bueno es lo que la documentación misma dice.

Solo basta con importar la clase, instanciar un objeto de la misma a través del método getLocalHost()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import java.net.InetAddress;
...
InetAddress ip;
try {
    ip = InetAddress.getLocalHost();
    System.out.print("ipLocal: ");
    System.out.println(ip.getHostAddress());
} catch (UnknownHostException e) {
    e.printStackTrace();
}

La salida será del estilo:
1
ipLocal: 10.0.0.157


También InetAddress nos permitirá conocer el nombre de la pc y el dominio:
1
2
3
4
System.out.print("nombre del PC: ");
System.out.println(ip.getHostName());
System.out.print("dominio del PC: ");
System.out.println(ip.getCanonicalHostName());

1
2
nombre del PC: Dar10-PC
dominio del PC: algunDominio



Ip pública


Para hallar nuestra ip pública debemos recurrir a un servicio como por ejemplo http://checkip.amazonaws.com

Este servicio de amazon, nos devuelve un InputStream con nada más ni nada menos que la ip del solicitando, pero nos vale para obtener nuestra propia ip publica.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
...
URL ipPublica;
BufferedReader in = null;
InputStreamReader isr = null;
try {
    ipPublica = new URL("http://checkip.amazonaws.com");
    isr = new InputStreamReader(ipPublica.openStream());
    in = new BufferedReader(isr);
    String ip = in.readLine(); 
    System.out.print("IP publica: ");
    System.out.println(ip);
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (in != null) {
            in.close();
        }
        if(isr != null){
            isr.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

1
IP publica: aqui va tu ip

[Métodos] Reemplazar caracteres con acento, tildes, signos diacriticos, etc

Mi problema, windows no acepta caracteres diacriticos para nombres de archivos o directorios, como los acentos graves y agudos ( ´ ) y ( ` ), el acento circunflejo ( ^ ), la diéresis ( ¨ ), la virgulilla ( ~ ), la cedilla ( ¸ ), la colita ( ˛ ), la coma ( , ), el doble acento agudo, ( ˝ ), el doble acento grave, ( `` ) , el carón ( ˇ ), el breve ( ˘ ), el macrón ( ˉ ), el anillo ( ˚ ), el punto ( • ) el garfio ( ̉ )
ja lo saque de wikipedia!

Entonces pense en removeer los caracteres que ningún sistema operativo permite.
1
String invalidCharRemoved = fileName.replaceAll("[\\\\/:*?\"<>|]", "");

Este patrón remueve aquellos caracteres que windows nos informa con una vigneta:

Pero aun asi, los acentos, la Ñ que si son admitos en la mayorias de distribuciones de windows siguen estando, pero justo el servidor productivo no era uno de ellos.
La siguiente solucion, aunque torpe, satisfacia la problematica y permitía a la aplicación seguir funcionando:
1
string.replace("á", "").replace("é", "").replace("í", "").replace("ó", "").replace("ú", "").replace("ñ", "")

Aunque funcional, a gusto personal no es aceptable:
1
evaluación desempeño región aledaños --> evaluacin desempeo regin aledaos

Para lo cual encontré 2 posibles soluciones: Java.text.Normalizer y org.apache.commons.lang3.StringUtils

Normalizer

1
2
3
4
5
6
import java.text.Normalizer;
...
private static String normalizeUsingJavaText(String source){
    source = Normalizer.normalize(source, Normalizer.Form.NFD);
    return source.replaceAll("[^\\p{ASCII}]", "");
}

Esto podria ser usado asi:
1
2
3
4
5
public static void main(String[] args){
    String string = "áéíóúñ";
    System.out.println(normalizeUsingJavaText(cadenaLoca()));
    //salida --> aeioun
}


StringUtils


Esta es un dependencia, y por lo cual hay que importarla por ejemplo con maven:
1
2
3
4
5
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.0</version>
</dependency>

Simplemente basta con llamar al metodo stripAccents:
1
2
3
4
5
6
import org.apache.commons.lang3.StringUtils;
...
private static String normalizeUsingApacheStringUtils(String source){
    String input = StringUtils.stripAccents(source);
    return input;
}

Esto lo implemente asi: (Esta fué la solución ganadora)
1
2
3
4
5
public static void main(String[] args){
    String string = "áéíóúñ";       
    System.out.println(normalizeUsingApacheStringUtils(string));
    // salida -> aeioun
}

[Métodos] Crear un jar ejecutable en IDE: eclipse, netbeans o intelliJ



Para poder crear un .jar de nuestro con nuestro IDE:

Eclipse:


Sobre la vista de nuestros proyecto, click derecho para acceder al menu contextual:


Damos click en Export..., para que nos abra un ventana de exportación


En la lista lista con carpeta que nos ofrece esta nueva ventana, elegimos Java, y esta contiene 3 opciones


Aqui elegiremos Runnable JAR file, para que sea autoejecutable.

El ultimo paso es elegir cual será la clase principal(Que contenga el método main) a traves de la cual se comenzara a ejecutar la aplicacion. En el combo Launch configuration que te da a elegir con todas las clases que contengan un metodo main ejecutable y a que proyecto pertenece.

Como asi tambien en Export destiantion la ruta completa donde estará el nuevo jar





Netbeans


PAra generar nuestro jar con NetBeans, hay que seleccionar nuestro proyecto desde la vista de proyectos, e ir al menu de la superior a la opcion Run


Para seleccionar una de las 2 opciones: Build Project o Clean and Build Project con el nombre entre parentesis del proyecto que tengamos seleccionado. Tambien nos da el atajo de teclado para hacerlo ;)

Luego podemos chequear el resultado en nuestra consola:


Con eso bastará para ir a la carpeta de nuestro proyecto, y buscar en la carpeta dist el jar generado.
En la consola se puede como genera el jar a través de comandos ejecutados en la consola con ant y te sugiere como hacer para correrlo




intelliJIDEA


Para generar un jar de nuestro proyecto en intelliJIDEA, de la manera que nos resulto, es ir al menu principal de la parte superior:


Sobre File >> Project structure para abrir la siguiente ventana:


Y en el menu de la izquierda, vamos a Project Setting y en el sub-menu de artifact, para hacer click en el + y posteriormente en el menu contextual: JAR >> From modules with dependencies


En la siguiente ventana, configuramos el proyecto y la clase principal.

Luego marcamos el ckeck Build on make para darle a aceptar

Por ultimo, cada vez que querramos generar nuestro jar, sobre el menu principal de la parte superior Build >> MakeProject, para generarlo en la ruta ..out/artifact/*.jar

[Métodos] Cómo crear un Jar ejecutable desde la consola y en un IDE


Consola CMD


Para poder generar un jar a través de la consola de windows debemos:

  1. Contar con la variable JAVA_HOME
    • Esta debe apuntar al root de JDK de la versión que tengamos.
    • De dudar si esta configurada, o entre tantas a cual apunta, podemos escribir en la consola:
    • 1
      2
      echo %JAVA_HOME%
      C:\Programs File\Java\jdk1.8.0_112
      
    • La respuesta deberia de ser la ruta a la carpeta de java, de lo contrario mostraria el literal "%JAVA_HOME%"


  2. Escribir una clase java con un metodo main
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package com.blogspot.dar10comyr;
    
    import java.awt.FlowLayout;
    import java.awt.Frame;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    
    public class Principal {
    
        public static void main(String[] args) {
            JLabel etiqueta = new JLabel("Hola mundo");
            Frame marco = new JFrame("LegenDar10");
            marco.setLayout(new FlowLayout());
            marco.add(etiqueta);
            marco.setLocationRelativeTo(null);
            marco.setSize(250, 100);
            marco.setVisible(true);
        }
    }
    


  3. Compilar el archivo java para convertirlo en .class
    • Hay que llamar al archivo javac.exe y a nuestro archivo java, con lo cual podría llamar a la ruta absoluta de cada cual o aprovechando tener la variable global JAVA_HOME, podemos abrir la consola desde la barra de direcciones en la carpeta donde esta nuestra clase:
    • 1
      "%JAVA_HOME%/bin/javac.exe" Principal.java
      
    • Es importante notar que generalmente la carpeta Program File, lleva un espacio por lo que es mejor encerrar la ruta con las comillas dobles.
    • La primera parte de esta sentencia, llama al compilador del jdk, el archivo javac.exe
    • Y como primer parametro le pasa la clase java que deseamos compilar.


  4. Configurar Main-Class
    • Esto se logra a traves del archivo Manifest.txt, este se situa sobre el root del proyecto
    • 1
      2
      Main-Class: com.blogspot.dar10comyr.Principal
      
      
    • Es un simple archivo de texto, pero de suma importancia su nombre, contiene pares de clave-valor separada por los dos puntos.
    • La clave Main-Class, con sus correspondientes mayusculas, indica cual es la calse principal del proyecto que contiene el metodo main
    • El valor com.blogspot.dar10comyr.Pricnipal, indica la clase a través de su nombre con los paquetes a los que pertence y sin extención, ya que existe el .java, humanamente leible y el .class, un archivo binario.
    • Es muy importante! que este archivo termine con un salto de linea, ya que de lo contrario, no sabra cuando termina la primera declaracion


  5. Generar el jar
    • suponiendo que la estructura de nuestro proyecto es:
      1
      2
      3
      C:/Proyecto/Manifest.tx
      C:/Proyecto/com/blogspot/dar10comyr/Pricipal.java
      C:/Proyecto/com/blogspot/dar10comyr/Pricipal.class
      
    • Llamaremos a través de la variable global JAVA_HOME, al archivo jar.exe
    • Con los puntos de entrada-cvfm, donde:
      • -c indica que creará un nuevo archivo, el .jar
      • -v nos brinda la información detalla del proceso
      • -f le da el nombre al jar, en nuestro caso Saludos.jar
      • -m indica que daremos la información del 'manifest.txt'
    1
    "%JAVA_HOME%/bin/jar.exe" -cvfm Saludos.jar manifest.txt com/blogspot/dar10comyr/Principal.class
    
    • Luego de la point-entry, le damos un nombre al jar, la ubicacion del manifest y de las clases


Ya por ultimo, desde la misma consola llamamos al archivo jar o dando dobel click, el resultado será:

[Métodos] Generar tabla en PDF con xstream y xls en Java


Imaginemos que contamos con un xml de la siguiente manera:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<list>
  <juego>
    <nombre>Rise Of The Tomb Raider</nombre>
    <desarrolladora>Square Enix</desarrolladora>
    <distribuidora>Crystal Dinamics</distribuidora>
    <plataformas>PC, PS4, XBOX ONE XBOX 360</plataformas>
    <genero>Accion Aventura </genero>
    <fechaLanzamiento>2015-11-10 03:00:00.0 UTC</fechaLanzamiento>
  </juego>
  <juego>
    <nombre>Far Cry Primal</nombre>
    <desarrolladora>Ubisoft Montreal</desarrolladora>
    <distribuidora>Ubisoft</distribuidora>
    <plataformas>PC, PS4, XBOX ONE</plataformas>
    <genero>Accion Aventura Mundo Abierto </genero>
    <fechaLanzamiento>2016-02-23 03:00:00.0 UTC</fechaLanzamiento>
  </juego>
  <juego>
    <nombre>Resident Evil 7 BioHazard</nombre>
    <desarrolladora>Capcom</desarrolladora>
    <distribuidora>Capcom</distribuidora>
    <plataformas>PC, PS4, XBOX ONE</plataformas>
    <genero>Survival Horror</genero>
    <fechaLanzamiento>2017-01-24 03:00:00.0 UTC</fechaLanzamiento>
  </juego>
</list>

Entonces la idea seria poder generar un tabla, similar a las HTML, para poder asemejar cada etiqueta juego como un columna de nuestra tabla.
La sintaxis a usar para una tabla es:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<fo:table border="solid">
    <!-- declarar aqui las columnas que sean necesarias -->
    <fo:table-column column-width="30mm" />
    <!-- declaramos un cabecera -->
    <fo:table-header>
        <fo:table-row>
            <fo:table-cell>
                <fo:block font-weight="bold">Titulo de la columna</fo:block>
            </fo:table-cell>
        </fo:table-row>
    </fo:table-header>
    <!-- declaramos el cuerpo de la tabla -->
    <fo:table-body>
        <fo:table-row>
            <fo:table-cell>
                <fo:block>
                    <xsl:text>contenido de la celda</xsl:text>
                </fo:block>
            </fo:table-cell>
        </fo:table-row>
    </fo:table-body>
</fo:table>

    Es muy importante respetar la secuencia de etiqueta
  • <table-body></table-body>
  • <table-row></table-row>
  • <table-cell></table-cell>
  • <fo-block></fo-block>
  • Ya que de lo contrario, el transformador no entenderá y no generará el reporte

Para poder iterar sobre todas las etiquetas 'juego' vamos a hacer uso del tag <xsl:for-each select="list/juego">, 'seleccionando' a list y por cada juego:

1
2
3
<xsl:for-each select="/">
    <!-- aqui se repite por cada elemento -->
</xsl:for-each>

El XSL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="/">
        <fo:root>
            <fo:layout-master-set>
                <fo:simple-page-master master-name="A4-portrait" page-height="29.7cm" page-width="21.0cm"
                    margin="1cm">
                    <fo:region-body />
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="A4-portrait">
                <fo:flow flow-name="xsl-region-body">

                    <fo:table border="solid">
                        <fo:table-column column-width="30mm" />
                        <fo:table-column column-width="30mm" />
                        <fo:table-column column-width="30mm" />
                        <fo:table-column column-width="35mm" />
                        <fo:table-column column-width="35mm" />
                        <fo:table-column column-width="30mm" />
                        <fo:table-header>
                            <fo:table-row>
                                <fo:table-cell>
                                    <fo:block font-weight="bold">Juego</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block font-weight="bold">Desarrolladora</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block font-weight="bold">Distribuidora</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block font-weight="bold">Fecha de Lanzamiento</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block font-weight="bold">Genero</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block font-weight="bold">Plataforma</fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                        </fo:table-header>
                        <fo:table-body>
                            <xsl:for-each select="list/juego">
                                <fo:table-row>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="nombre" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="desarrolladora" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="distribuidora" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="fechaLanzamiento" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="genero" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="plataformas" />
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>
                            </xsl:for-each>
                        </fo:table-body>
                    </fo:table>

                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
</xsl:stylesheet>



Clase de ayuda con el método de transformacion


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package dar10;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;

public class FopHelper {

    public void xmlString2Pdf(String xml, String xslPath, String pdfPath) throws IOException, FOPException, TransformerException{
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        OutputStream out;
        out = new FileOutputStream(pdfPath);

        try {
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            // Ubicacion del archivo XSL
            File xsltFile = new File(xslPath);
            Source xslSource = new StreamSource(xsltFile);
            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(xslSource);

            // Resulting SAX events (the generated FO) must be piped through to FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            // Se convierte a 'Source' el xml
            StringReader reader = new StringReader(xml);
            Source xmlSource = new StreamSource(reader);

            // se crea el PDF
            transformer.transform(xmlSource, res);
        } finally {
            out.close();
        }
    }

    public void xmlFile2Pdf(String xmlPath, String xslPath, String pdfPath) throws IOException, FOPException, TransformerException{
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        OutputStream out;
        out = new FileOutputStream(pdfPath);

        try {
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            // Ubicacion del archivo XSL
            File xsltFile = new File(xslPath);
            Source xslSource = new StreamSource(xsltFile);
            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(xslSource);

            // Resulting SAX events (the generated FO) must be piped through to FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            // Se convierte a 'Source' el xml
            File xmlFile= new File(xmlPath);
            Source xmlSource = new StreamSource(xmlFile);

            // se crea el PDF
            transformer.transform(xmlSource, res);
        } finally {
            out.close();
        }
    }

}



La llamada


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public static String xmlPath = "src//dar10//juegos.xml";
public static String xslPath = "src//dar10//template.xsl";
public static String pdfPath = "src//dar10//resultado.pdf";

public static void main(String...Legendar10){
    FopHelper fopHelper = new FopHelper();
    try {
        fopHelper.xmlFile2Pdf(xmlPath, xslPath, pdfPath);
    } catch (FOPException | IOException | TransformerException e) {
        e.printStackTrace();
    }
}



El resultado


[Métodos] Generar PDF con xls en Java - Hola Mundo


Apache FOP, de sus siglas en inglés Formatting Objects Processor, el equivalente en español de Procesador de formato de objetos, es un formateador de impresión a través de archivos XSL formatting objects (XMLFO)
Según el mismo framework es capaz de imprimir en muchisimos formatos:
  • PDF, el mas típico y más usado
  • ASCII, PostScript, Direct printer output (PCL), AFP, RTF, Java2D/AWT, menos usuales

Esquema

El esquema básico es se toman tanto el xml como string que genero con xstream, dado en un webservice como desde un archivo, junto al xsl para ser procesados en java a través de apache FOP para generar un pdf(sigla del inglés Portable Document Format, «formato de documento portátil»)



Método

  • Declara 2 objetos FOPFactory y de éste instancia FOUserAgent que servirá para crear el FOP
  • También declara un OutputStream con el path de salida donde se creara el archivo
  • Estos los usa para instancia el objeto FOP junto a una constante que indica que será del tipo PDF
  • Con el path del archivo xsl crea un File y a partir de este un StreamSource que hereda de Source
  • Se crea un TransformerFactory para que junto al xsl instancie un Transformer que procece el xml
  • Declara un objeto Result instanciando un SAXResutl a partir del objeto 'fop'
  • Crea un Source, instanciando StreamSource pero esta vez a partir de un StringReader ya que se trata esta vez de un xml como String.
    Este paso puede cambiar instanciando el streamsource con un objeto file con el path del archivo xml, de igual manera que se hace con xsl.
  • Y el ultimo paso de esta receta mágica, es que el objeto Transformer transforme la fuente del xml junto con el resultado para crear el PDF

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static String xml = "<valor>Mundo</valor>";
public static String xslPath = "src//dar10//template.xsl";
public static String pdfPath = "src//dar10//resultado.pdf";

public static void main(String...Legendar10) throws IOException, FOPException, TransformerException{
    //Setea el agente para el FOP
    FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

    OutputStream out = new FileOutputStream(pdfPath);

    try {
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        // Ubicacion del archivo XSL
        File xsltFile = new File(xslPath);
        Source xslSource = new StreamSource(xsltFile);
        // Transformer a partir del xslt
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(xslSource);

        // Resulting SAX events (the generated FO) must be piped through to FOP
        Result res = new SAXResult(fop.getDefaultHandler());

        // Se convierte a 'Source' el xml
        StringReader reader = new StringReader(xml);
        Source xmlSource = new StreamSource(reader);

        // se crea el PDF
        transformer.transform(xmlSource, res);
    } finally {
        out.close();
    }
}

En este caso esta todo contendio en un método main que ejecuta el proceso java. Se crea del proyecto un solo paquete que lo he llamado 'dar10' y los 3 string declarados como estaticos que representan el xml, la ubicacion del xsl, y la ubicacion de destino (que son el mismo paquete dentro del proyecto)

Añadir dependencias en el pom/classpath


1
2
3
4
5
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.10</version>
</dependency>


El XSL (Transformador)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <fo:root>
      <fo:layout-master-set>
        <fo:simple-page-master master-name="A4-portrait"
              page-height="29.7cm" page-width="21.0cm" margin="2cm">
          <fo:region-body/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="A4-portrait">
        <fo:flow flow-name="xsl-region-body">
          <fo:block>
            Hola, <xsl:value-of select="valor"/>!
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>
</xsl:stylesheet>

El xsl declara en su etiquetas:
  • la version de stylesheet
  • que la fuente de datos será xml
  • que el root del xml empieza en "/" y es a partir de lo que contengan intermente estas etiquetas, aunque nuestro xml solo contiene un tag
  • tmabién declara un layout por defecto y al 'Documento' con las dimensiones de la pagina (A4) y un cuerpo (body)
  • en las etiquetas siguientes declara 'page-sequence' y 'flow' haciendo referencias las anterior mencionadas
  • Y aqui comienza lo bueno, simplemente declara un fo:block, como un contenedor 'div'
  • y buscará con xsl:value-of dentro del root que estemos posicionados ("/") el valor contenido por las etiquetas 'valor'


El resultado:


Java 25 de 2025