CSV
Purpose¶
A general purpose comma separated values (CSV) format parser with inbuilt validation and output format templating.
Methods¶
Binding name: p6.csv
Method: void parse(Map configuration, Closure rowNotify)
Parses the CSV file specified in the configuration map and calls the given closure with each row processed.
Method: List parseToList(Map configuration)
Parses the CSV file specified in the configuration map returning the processed values as a List or Maps.
Method: int parseToXml(Map configuration, Closure docNotify)
Parses the CSV file specified in the configuration map and calls the given docNotify closure with each XML document generated. This method returns the number of XML documents generated.
Configuration map
Configuration Name | Description |
---|---|
separator | Optional. See: http://opencsv.sourceforge.net/apidocs/com/opencsv/CSVParserBuilder.html |
quoteChar | Optional. See: http://opencsv.sourceforge.net/apidocs/com/opencsv/CSVParserBuilder.html |
escape | Optional. See: http://opencsv.sourceforge.net/apidocs/com/opencsv/CSVParserBuilder.html |
skipLines | Optional. See: http://opencsv.sourceforge.net/apidocs/com/opencsv/CSVParserBuilder.html |
strictQuotes | Optional. See: http://opencsv.sourceforge.net/apidocs/com/opencsv/CSVParserBuilder.html |
ignoreLeadingWhiteSpace | Optional. See: http://opencsv.sourceforge.net/apidocs/com/opencsv/CSVParserBuilder.html |
useFirstLineHeaders | Optional. Set to true to read column descriptions from the first line of the csv. These column names will be used in all row Maps returned. Otherwise column name are col0..colN. The default is false. |
validation | Optional. A Map of column numbers and the name of a valid content type. Type names are: date, byte, short int,long, double float, email, url and creditcard. See: http://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/GenericValidator.html. If a value is null or empty, validation is not applied. If validation is applied and fails then a P6Exception is thrown. |
groovyTemplate | One of five groovy template types. Mandatory for parseToXml. See: http://docs.groovy-lang.org/next/html/documentation/template-engines.html |
uri | Mandatory. A file to open and use as the CSV input source (expressed as a string). |
funcNext | Optional closure. Parameters (lastrow, currentrow). Used by parseToXml. Return true to generate Xml document false to continue accumulating data |
funcValidate | Optional closure. Paramaters (row, column, value). Called each time a value in a row is validated. Return null or an empty string to signify the value is valid. Or return a message detailing why the validation has failed. |
funcException | Optional closure. Parameters (row, column, value, message). Called each time the validation of a value in a row fails. Return true continue processing on the next row. Return false to exit the processor with a P6Exception. |
Closure
A single parameters containing an array of rows is passed to the closure.
Each row is a map that uses the column names as keys if useFirstLineHeaders
is set to true.
Examples¶
Simple parse of CSV file with notification per row.
def cnf = [
skipLines: 1,
separator: ',',
useFirstLineHeaders: true,
uri:"file:./src/test/resources/test1.csv"
]
p6.csv.parse(cnf) { row ->
println(row)
// Could validate the row content in here and return false to halt the parse
true
}
In memory parse of CSV file. Results returned as a List or Map.
def cnf = [
skipLines: 1,
separator: ',',
useFirstLineHeaders: true,
uri:"file:./src/test/resources/test1.csv"
]
p6.csv.parseToList(cnf).inject(0) { i, entry->
println(entry)
}
Parse CSV file to XML with document stepping control via the script; notifications per document generated.
def tpl = '''
<response version-api="2.0" xmlns:gsp="http://groovy.codehaus.org/2005/gsp">
<value>
<addresses>
<gsp:scriptlet>rows.eachWithIndex{row,index-></gsp:scriptlet>
<address id="${index}">
<!-- You can use GString expressions -->
<uniqueid>${row.UniqueName}</uniqueid>
<name id="${index}">
<!-- Or you can use expression tags as well -->
<gsp:expression>row.Name</gsp:expression>
</name>
</address>
<gsp:scriptlet>}</gsp:scriptlet>
</addresses>
</value>
</response>
'''
def cnf = [
skipLines: 1,
useFirstLineHeaders: true,
uri:"file:./src/test/resources/test1.csv",
groovyTemplate: new groovy.text.XmlTemplateEngine().createTemplate(tpl),
funcNext: { lastrow, currentrow ->
if(null != lastrow){
if(lastrow.Name != currentrow.Name){
// Change of name so build xml
return true
}
}
false
}
]
def docs = p6.csv.parseToXml(cnf){ gpath ->
println(XmlUtil.serialize(gpath))
}
Alternative Groovy template engines
Groovy currently provides five template engines. Each engine supports a different template syntax and is suited to a different task:
- SimpleTemplateEngine
- StreamingTemplateEngine
- XmlTemplateEngine
- GStringTemplateEngine
- MarkupTemplateEngine
For further details see: http://docs.groovy-lang.org/next/html/documentation/template-engines.html
Here is an example of using the SimpleTemplateEngine.
def tpl2 = '''
<response>
<value>
<addresses>
<% rows.eachWithIndex{row,index-> %>
<address id="${index}"><uniqueid>${row.UniqueName}</uniqueid><name id="${index}">${row.Name}</name></address>
<% } %>
</addresses>
</value>
</response>
'''
def cnf2 = [
skipLines: 1,
useFirstLineHeaders: true,
uri:"file:/Users/simont/Documents/temp/test.csv",
groovyTemplate: new groovy.text.SimpleTemplateEngine().createTemplate(tpl2),
funcNext: { lastrow, currentrow ->
if(null != lastrow){
if(lastrow.Name != currentrow.Name){
// Change of name so build xml
return true
}
}
false
}
]
def docs = p6.csv.parseToXml(cnf2){ gpath ->
println(groovy.xml.XmlUtil.serialize(gpath))
}
Simple parse of CSV file with notification per row and validation or column vales 1 and 17.
def cnf = [
skipLines: 1,
separator: ',',
useFirstLineHeaders: true,
uri:"file:./src/test/resources/test1.csv",
validation: [1: 'int', 17: 'date']
]
p6.csv.parse(cnf) { row ->
println(row)
true
}
Simple parse of CSV file with notification per row and complex validation rule and exception handler.
def cnf = [
skipLines: 1,
separator: ',',
useFirstLineHeaders: true,
uri:"file:./src/test/resources/test1.csv",
funcValidate: { row, column, value ->
if(column == 8 && value == "1946437"){
"This is not the droid you are looking for! row:" + row
}
else { "" }
},
funcException: { row, column, value, message ->
println("Ooops! " + message)
// true to continue processing
true
}
]
p6.csv.parse(cnf) { row ->
println(row)
true
}