xml using encoding UTF-8 witout BOM groovy - groovy

Hi I need to create a XML file in groovy using MarkupBuilder class, the xml file should have encoding utf-8 without BOM.
This is my code that generate a markupbuilder and add a encoding
def textXML = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(textXML)
builder.setDoubleQuotes(false)
builder.setOmitNullAttributes(true)
builder.setOmitEmptyAttributes(true)
builder.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
//some more code
This code creates the xml file
def file = new File("fileXml.xml")
file << textXML
But the generate xml is always with encoding utf-8 with BOM
How solve this?
Thanks!

the UTF-8 BOM (Byte Order Marker) is always the first three bytes of the file. You can simply remove them.
I would do something like this:
def textXML = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(textXML)
builder.setDoubleQuotes(false)
builder.setOmitNullAttributes(true)
builder.setOmitEmptyAttributes(true)
builder.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
def xmlbytes = textXML.toString().getBytes().flatten()
xmlbytes.remove(0)
xmlbytes.remove(0)
xmlbytes.remove(0)
def file = new File("fileXml.xml")
file << xmlbytes
That's how I'd do it. Pardon the java-ness of my Groovy -- old habits die hard.

So my situation is slightly different. I'm trying to write an XML using MarkupBuilder and have the BOM appear (new customer requirement). So far, everything I try yields just a plain text XML file with no BOM. Here's my sample code:
import groovy.xml.MarkupBuilder
def writer = new StringWriter()
def xml = new MarkupBuilder( writer )
xml.setDoubleQuotes(false)
xml.setOmitNullAttributes(true)
xml.setOmitEmptyAttributes(true)
xml.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
xml.quote() {
xml.quote_details() {
xml.detail() {
xml.quoteId('Q1339', type:'FCL')
}
}
}
new FileOutputStream('UTF_test.xml').withWriter('UTF-8') { w ->
w.write('ABC')
w << writer
}
The "ABC" will show up in the file, but no BOM. My backup plan is to just export the characters myself, but this seems less elegant.

Related

How to read a file in Groovy into a string, without knowing the path to the file?

In extension to this question.
Is it possible to read a file into a string without knowing the path to the file? - I only have the file as a 'def'/type-less parameter, which is why I can't just do a .getAbsolutePath()
To elaborate on this, this is how I import the file (which is from a temporary .jar file)
def getExportInfo(path) {
def zipFile = new java.util.zip.ZipFile(new File(path))
zipFile.entries().each { entry ->
def name = entry.name
if (!entry.directory && name == "ExportInfo") {
return entry
}
}
}
A ZipEntry is not a file, but a ZipEntry.
Those have almost nothing in common.
With def is = zipFile.getInputStream(entry) you get the input stream to the zip entry contents.
Then you can use is.text to get the contents as String in the default platform encoding or is.getText('<theFilesEncoding>') to get the contents as String in the specified encoding, exactly the same as you can do on a File object.

SoapUI/Groovy: expand txt file, NOT re-write it

There is no problem to save response sheet to file. Smth like
def xmlFile = "C:/.../Try.xml"
def response = context.expand( '${Request#Response}' )
def f = new File(xmlFile)
f.write(response, "UTF-8")
BUT.
I re-run my request in groovy script with new parameters (using while), and I need to ADD info to result file, not to re-write it. Now it's just re-writing each time:(. File created outside the cycle.
Thanks in advance,
Dmitry
straight from the ref-doc
new File('TestFile1.txt').withWriterAppend( 'UTF-8' ){ w->
w << 'abcdefghij'
}

In SoapUI , .docx file creation of xml pretty print by groovy and Apache poi, how?

I have wrote an groovy script in soapui for .docx file creation, its working fine and printing also . But the request XML and response XML are not coming in Pretty print , its coming as a paragraph.
import java.io.FileInputStream;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.*;
def groovy=new com.eviware.soapui.support.GroovyUtils(context)
def project=context.testCase.testSuite.project
def testStepCount= testRunner.testCase.getTestStepCount();
log.info testStepCount
def request=project.getTestSuiteAt(0).getTestCaseAt(1).getTestStepAt(4).getProperty("Request").getValue().toString()
XWPFDocument docx = new XWPFDocument(new FileInputStream("c:\\Inputparagraph.docx"));
FileOutputStream out = new FileOutputStream(new File("C:\\createparagraph00.docx"));
XWPFParagraph p2 = docx.createParagraph();
XWPFRun r2 = p2.createRun();
r2.setText(request);
docx.write(out);
out.close();
And the output looks like:
you can split your input and add multiple runs with line breaks. see the XXX tagged part
#Grapes([#Grab('org.apache.poi:poi-ooxml:3.11'),#Grab('org.apache.poi:ooxml-schemas:1.1')])
import java.io.FileInputStream
import org.apache.poi.xwpf.usermodel.*
def sometext='''\
A
BC
D'''
XWPFDocument docx = new XWPFDocument()
FileOutputStream out = new FileOutputStream(new File("/tmp/out.docx"))
XWPFParagraph p = docx.createParagraph()
// XXX
sometext.eachLine{ line ->
p.createRun().with{
setText(line)
addBreak()
}
}
docx.write(out)
out.close()
BTW: you don't need ; to end lines in groovy

XmlSlurper and http.get in groovy

I first save a txt file using http.get:
http.get(path: path,
contentType: TEXT,
query: [id:dapId, instance:alias, format:'xml', file:portalFile]) {resp, reader ->
println "response status: ${resp.statusLine}"
println 'Headers: -----------'
resp.headers.each { h ->
println " ${h.name} : ${h.value}"
}
new File(outputFileName).withWriter{out -> out << reader}
}
And then use the newly created file in outputFileName in XmlSlurper().parse, as below:
def inputFile = new File(outputFileName)
def domain = new XmlSlurper().parse(inputFile)
But I get an error when doing new XmlSlurper().parse(inputFile):
Caught: org.xml.sax.SAXParseException: White spaces are required between publicId and systemId.
I noticed that the textfile outputFileName which is being created with http.get seems to be an HTML file and not an XML file. So I copied and pasted the XML code which it is supposed to contain into outputFileName, skipped the first part of the code and only ran the XmlSlurper().parse() bit and it worked.
Is outputFileName supposed to be an xml file? It has lots of HTML tags.
Thanks in advance! :D
HTML != XML. Your HTML file probably is not valid XML. Therefore, the XML parser fails during parsing. Are you sure that the file created from the http GET is a valid XML file?

Groovy load .csv files

How to read and import .csv file in groovy on grails. I have .csv file with data and
need to import in to db using user interface .
There are as always different possibilities to work with CSV files in Groovy.
As Groovy is fully interoperable with Java, you can use one of the existing CSV libararies, e.g. OpenCSV.
Depending on the complexity of the CSV file you are using, you can also use the standard file/string handling possibilities of Groovy:
def sql = Sql.newInstance("jdbc:mysql://localhost:3306/mydb",
"user", "pswd", "com.mysql.jdbc.Driver")
def people = sql.dataSet("PERSON")
new File("users.csv").splitEachLine(",") {fields ->
people.add(
first_name: fields[0],
last_name: fields[1],
email: fields[2]
)
}
EDIT:
Kelly Robinson just wrote a nice blog post about the different possibilities that are available to work with CSV files in Groovy.
EDIT #2:
As Leonard Axelsson recently released version 1.0 of his GroovyCVS library, I thought I should definitely add this to the list of options.
Using xlson's GroovyCSV:
#Grab('com.xlson.groovycsv:groovycsv:1.3')
import static com.xlson.groovycsv.CsvParser.parseCsv
for(line in parseCsv(new FileReader('countries.csv'), separator: ';')) {
println "Country=$line.COUNTRY, Capital=$line.CAPITAL"
}
The field names are taken from the header of the CSV file.
If the CSV file has no header, you can specify the field names programmatically.
With Apache Commons-CSV
#Grab('org.apache.commons:commons-csv:1.2')
import org.apache.commons.csv.CSVParser
import static org.apache.commons.csv.CSVFormat.*
import java.nio.file.Paths
Paths.get('countryInfo.txt').withReader { reader ->
CSVParser csv = new CSVParser(reader, DEFAULT.withHeader())
for (record in csv.iterator()) {
println record.dump()
}
}
Commons-CSV has nice API and I recommend that.
With GroovyCSV:
#Grab('com.xlson.groovycsv:groovycsv:0.2')
import com.xlson.groovycsv.CsvParser
def csv = '''Name,Lastname
Mark,Andersson
Pete,Hansen'''
def data = new CsvParser().parse(csv)
for(line in data) {
println "$line.Name $line.Lastname"
}
(Taken from it's samples)
Last resort: Regular expression.
Here's how I parsed a file that might contain a quoted escaped string in it's fourth column:
File detailedStatsFile = new File("stats.csv");
detailedStatsFile.eachLine { line, number ->
// Number Of Executions, Total Milliseconds, Milliseconds per execution, "Type"
def match = line =~ /([^,]*?),\s*([^,]*?),\s*([^,]*?),\s*(?:([^",]+)|(?:"((?:[^\\"]++(?:\\")?)++)"))$/; //"
if (!match.matches())
continue;
def numberOfExecs = Integer.valueOf(match.group(1));
def totalMillis = Integer.valueOf(match.group(2));
def detailedStatName = match.group(4);
if (detailedStatName == null)
detailedStatName = match.group(5).replaceAll('\\"','"');
Example using opencsv
#Grab('com.opencsv:opencsv:4.0')
import com.opencsv.CSVReader
import com.opencsv.CSVWriter
class TestCsvReader {
static main(args) {
def csv = '''"a","b","c"
"d","e","f"
'''
def Reader csvFileReader = new StringReader(csv)
def Writer csvFileWriter = new PrintWriter(System.out)
def CSVReader reader = new CSVReader(csvFileReader)
def CSVWriter writer = new CSVWriter(csvFileWriter)
reader.iterator().each { fields ->
writer.writeNext(fields)
}
reader.close()
writer.close()
}
}
Example from production code done by SAP developers in SCPi SAP Cloud Platform Integration groovy iFlow:
String[] parseCSVLine(String line) {
// Create a pattern to match breaks
Pattern p =
Pattern.compile(",(?=([^\"]*\"[^\"]*\")*(?![^\"]*\"))");
// Split input with the pattern
String[] fields = p.split(line);
for (int i = 0; i < fields.length; i++) {
// Get rid of residual double quotes
fields[i] = fields[i].replace("\"", "");
}
return fields;
}
Usage:
cols = parseCSVLine(line)
value = cols[0]
value = cols[1]
I prefer a slight tweak on the accepted answer: zip the columns and values together, as opposed to indexing each one by number. The result is slightly shorter code.
def sql = Sql.newInstance("jdbc:mysql://localhost:3306/mydb", "user", "pswd", "com.mysql.jdbc.Driver")
def people = sql.dataSet("PERSON")
def columns = ['first_name', 'last_name', 'email']
new File("users.csv").splitEachLine(",") {values ->
people.add([columns, values].transpose().collectEntries())
}

Resources