XSL - Multiples archivos con XSLT & Saxon en Java

 
Vista:
Imágen de perfil de Alberto

Multiples archivos con XSLT & Saxon en Java

Publicado por Alberto (1 intervención) el 23/03/2015 21:18:29
Que tal amigos, soy nuevo en el foro y aquí vengo con un nuevo tema para ustedes, espero puedan apoyarme, como dice el título del tema, tengo un pequeño inconveniente con las hojas de estilo XSL, soy nuevo con las plantillas y no estoy seguro si estoy realizando las cosas correctamente.

Tengo una carpeta con archivos de texto como se muestra a continuación.

descarga1.txt
descarga2.txt
descarga3.txt
...

Dichos archivos se necesitan convertir a un archivo XML, el cual realizo correctamente con la implementación del código siguiente.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />

<xsl:variable name="text" select="tokenize(unparsed-text('file:///C:/Users/Quality/Documents/ProyectoComerciales/download_files/descarga01.txt'),'&#xD;&#xA;')" />

<xsl:template name="main" match="/">
<content>
<items>
<xsl:for-each select="$text">
<xsl:variable name="idi" select="substring(.,1,2)" />
<xsl:if test="$idi = 'OH'">
<item>
<xsl:element name="id"><xsl:value-of select="$idi" /></xsl:element>
<xsl:element name="folio"><xsl:value-of select="substring(.,3,10)" /></xsl:element>
</item>
</xsl:if>
</xsl:for-each>
</items>
<products>
<xsl:for-each select="$text">
<xsl:variable name="idp" select="substring(.,1,2)" />
<xsl:if test="$idp = 'BL'">
<product>
<xsl:element name="id"><xsl:value-of select="$idp" /></xsl:element>
<xsl:element name="code"><xsl:value-of select="substring(.,3,18)" /></xsl:element>
</product>
</xsl:if>
</xsl:for-each>
</products>
<users>
<xsl:for-each select="$text">
<xsl:variable name="idu" select="substring(.,1,2)" />
<xsl:if test="$idu = 'LH'">
<user>
<xsl:element name="id"><xsl:value-of select="$idu" /></xsl:element>
<xsl:element name="num"><xsl:value-of select="substring(.,3,6)" /></xsl:element>
</user>
</xsl:if>
</xsl:for-each>
</users>
</content>
</xsl:template>
</xsl:stylesheet>

Si realizamos la llamada desde Java a este archivo tendremos una conversión exitosa, sin embargo, como podrán ver en la tercera línea del código se puede observar que yo le estoy diciendo que archivo quiero que lea, por lo tanto ahí es donde viene mi problema. Necesito que lea todos los archivos que se encuentran dentro de mi carpeta y valla creando un XML por cada archivo que va leyendo, investigue en Internet que puedo implementar la función collection() que el mismo XSL tiene, por lo que quedaría de la siguiente manera.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>

<xsl:template name="main" match="/">
<xsl:for-each select="collection('file:///C:/Users/Quality/Documents/ProyectoComerciales/download_files/?select=*.txt')">
<xsl:variable name="file" select="tokenize(document-uri(.),'/')[last()]"/>
<xsl:variable name="text" select="tokenize(unparsed-text($file),'&#xD;&#xA;')"/>
<xsl:for-each select="$text">
<content>
...
</content>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Sin embargo, cuando realizo la ejecución obtengo el siguiente mensaje de error "el contenido no está permitido en el prólogo". La llamada desde Java la realizo mediante el uso del siguiente código Saxon (saxon9he.jar)

try {
Processor proc = new Processor(false);
XsltCompiler comp = proc.newXsltCompiler();
XsltExecutable exp = comp.compile(new StreamSource(new File("C:/Users/Quality/Documents/" +
"ProyectoComerciales/xsl/convertir.xsl")));
Serializer out = new Serializer();
out.setOutputProperty(Serializer.Property.METHOD, "xml");
out.setOutputProperty(Serializer.Property.INDENT, "yes");
out.setOutputFile(new File("C:/Users/Quality/Documents/ProyectoComerciales/xml/descarga.xml"));
XsltTransformer trans = exp.load();
trans.setInitialTemplate(new QName("main"));
trans.setDestination(out);
trans.transform();
} catch (SaxonApiException sae) {
sae.printStackTrace();
}

Serían tan amables de apoyarme con este tema, de antemano, gracias por su tiempo.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Alejandro

Conversión de múltiples archivos de texto a XML

Publicado por Alejandro (227 intervenciones) el 07/07/2023 17:28:18
Para solucionar el problema de leer múltiples archivos de texto y generar un XML para cada archivo utilizando XSLT, se puede utilizar una combinación de técnicas. Sin embargo, hay algunas limitaciones con el uso de la función `collection()` en XSLT 2.0 y algunas implementaciones, como Saxon, pueden no admitirlo completamente.

Aquí hay una alternativa utilizando Java y el enfoque de procesamiento por lotes:

1. Crea un archivo XSLT llamado "convertir-batch.xsl" con el siguiente contenido:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
 
  <xsl:template match="/">
    <xsl:for-each select="document-uri(collection('file:///C:/Users/Quality/Documents/ProyectoComerciales/download_files/?select=*.txt'))">
      <xsl:variable name="fileName" select="tokenize(., '/')[last()]"/>
      <xsl:variable name="text" select="tokenize(unparsed-text(.), '&#xD;&#xA;')"/>
      <xsl:result-document href="file:///C:/Users/Quality/Documents/ProyectoComerciales/xml/{$fileName}.xml">
        <content>
          <!-- Tu lógica para procesar el texto y generar el XML -->
        </content>
      </xsl:result-document>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

2. Actualiza tu código Java para cargar y aplicar el nuevo archivo XSLT "convertir-batch.xsl":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try {
  Processor proc = new Processor(false);
  XsltCompiler comp = proc.newXsltCompiler();
  XsltExecutable exp = comp.compile(new StreamSource(new File("C:/Users/Quality/Documents/ProyectoComerciales/xsl/convertir-batch.xsl")));
  Serializer out = new Serializer();
  out.setOutputProperty(Serializer.Property.METHOD, "xml");
  out.setOutputProperty(Serializer.Property.INDENT, "yes");
 
  // Obtiene la lista de archivos de texto en la carpeta
  File[] files = new File("C:/Users/Quality/Documents/ProyectoComerciales/download_files/").listFiles();
  for (File file : files) {
    XsltTransformer trans = exp.load();
    trans.setInitialTemplate(new QName("main"));
    // Pasa el nombre del archivo actual como parámetro al XSLT
    trans.setParameter(new QName("input-file"), file.getAbsolutePath());
    trans.setDestination(out);
    trans.transform();
  }
} catch (SaxonApiException sae) {
  sae.printStackTrace();
}

3. Asegúrate de reemplazar la ruta de la carpeta y las rutas de archivo relevantes con las correctas en tu entorno.

Con este enfoque, se procesarán todos los archivos de texto en la carpeta especificada y se generará un archivo XML para cada uno, utilizando el nombre del archivo original como base para el nombre del archivo XML resultante.

Ten en cuenta que este enfoque utiliza la función `result-document` de XSLT 2.0 para generar los archivos XML por separado. Asegúrate de que tu implementación de XSLT admita esta función.

Espero que esto te ayude a solucionar tu problema.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar