I captured Roger's example from this email and put in on github here with a 
test.

https://github.com/OpenDFDL/examples/tree/master/xslt-csv

This isn't part of Daffodil, but it's an interesting example combining XSLT 
with Daffodil.

________________________________
From: Roger L Costello <coste...@mitre.org>
Sent: Tuesday, June 2, 2020 12:10 PM
To: users@daffodil.apache.org <users@daffodil.apache.org>
Subject: Here's how XSLT programs can use DFDL/Daffodil


Hi Folks,



Below is an XSLT program that processes XML-formatted CSV. The XSLT program 
calls an external Java program, passing it the name of a DFDL file 
(csv.dfdl.xsd) and the name of a CSV file (csv.txt). The Java program calls 
Daffodil which produces XML-formatted CSV. The Java program returns the XML as 
a string. The XSLT program uses the parse-xml() function to convert the string 
to XML.



<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:xs="http://www.w3.org/2001/XMLSchema";
    xmlns:dfdl="java:runDaffodil"
    version="3.0">

    <xsl:variable name="dfdl" select="'csv.dfdl.xsd'"/>
    <xsl:variable name="input" select="'csv.txt'"/>

    <xsl:template match="/">
        <!-- Convert the CSV text file to XML using DFDL -->
        <xsl:variable name="csv-string" select="dfdl:dfdlParse($dfdl, $input)" 
as="xs:string"/>
        <xsl:variable name="csv-xml" select="parse-xml($csv-string)" 
as="document-node()"/>
        <!-- Process the XML-formatted CSV here -->
        <xsl:variable name="numRecords" select="count($csv-xml//record)" 
as="xs:integer"/>
        <!-- Output the number of records in the CSV file -->
        <xsl:sequence select="$numRecords" />
        <!-- Output the model (field 3) and year (field 1) of each Chevy auto 
-->
        <xsl:for-each select="$csv-xml//record[field[2] eq 'Chevy']">
            <xsl:sequence select="(field[3]/data(), ' ', field[1]/data())" />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>



The XSLT program uses XSLT version 3.0. You can use any version except 1.0 (the 
parse-xml() function is not present in XSLT 1.0). I used Saxon as the XSLT 
processor.



The Java program calls Daffodil which parses the CSV file using the DFDL 
schema. Here is the Java program:



import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

import org.jdom2.Document;
import org.jdom2.output.XMLOutputter;

import org.apache.daffodil.japi.Compiler;
import org.apache.daffodil.japi.Daffodil;
import org.apache.daffodil.japi.DataProcessor;
import org.apache.daffodil.japi.Diagnostic;
import org.apache.daffodil.japi.ParseResult;
import org.apache.daffodil.japi.ProcessorFactory;
import org.apache.daffodil.japi.infoset.JDOMInfosetOutputter;
import org.apache.daffodil.japi.io.InputSourceDataInputStream;

public class runDaffodil {

    public static String dfdlParse(String dfdl, String input) throws 
IOException, URISyntaxException {

        URL dfdlURL = runDaffodil.class.getResource(dfdl);
        URL inputURL = runDaffodil.class.getResource(input);

        //
        // First, compile the DFDL Schema
        //
        Compiler c = Daffodil.compiler();
        ProcessorFactory pf = c.compileSource(dfdlURL.toURI());
        DataProcessor dp = pf.onPath("/");

        //
        // Parse - parse data to XML
        //
        java.io.InputStream is = inputURL.openStream();
        InputSourceDataInputStream dis = new InputSourceDataInputStream(is);

        //
        // Setup JDOM outputter
        //
        JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();

        //
        // Do the parse
        //
        ParseResult res = dp.parse(dis, outputter);

        //
        // Return the XML as a string
        //
        Document doc = outputter.getResult();
        return new XMLOutputter().outputString(doc);
    }
}




Reply via email to