Project

Profile

Help

RE: to find out in general which line in the source xml c... » TransformXML.java

luba zlatin, 2017-04-12 10:45

 
package transform;



import net.sf.saxon.lib.StandardLogger;
import net.sf.saxon.s9api.*;

import net.sf.saxon.trace.XSLTTraceListener;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.ValidationException;

//import org.apache.commons.lang3.StringUtils;


import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
* Model loading scheme XSLT processing engine.
*/
class TransformXML {

//private static final ILogger logger = new Logger(ModelLoadingSchemeXsltProcessor.class);

private static final String REFERENCE_PRODUCT_PARAM_NAME = "refProdDoc";

private Processor processor;
private Serializer serializer;
private XsltCompiler xsltCompiler;
private XsltExecutable xsltExecutable;
private XsltTransformer xsltTransformer;
private DocumentBuilder documentBuilder;


private List<String> transformationLog = new ArrayList<>();

/**
* Receiver for XSLT compilation errors and warnings. It is consumed by {@code XsltCompiler}.
* In the case of error() and warning(), the XSLT processor is required to continue processing
* the document until the end. For fatalError() the XSLT processor is not required to continue.
*/
private class ErrorListenerImpl implements ErrorListener {
@Override
public void error(TransformerException exception) throws TransformerException {
String message = getUserFriendlyMessage(exception);
if (!transformationLog.contains(message)) {
transformationLog.add(message);
}
}

@Override
public void fatalError(TransformerException exception) throws TransformerException {
String message = getUserFriendlyMessage(exception);
if (!transformationLog.contains(message)) {
transformationLog.add(message);
}
}

@Override
public void warning(TransformerException exception) throws TransformerException {
//logger.warning("", exception);
}
}
/**
* Receiver for custom XSLT debug messages in the form of {@code xsl:message}. It is consumed
* by @{code XsltTransformer}.
*/
private class MessageListenerImpl implements MessageListener {
@Override
public void message(XdmNode content, boolean terminate, SourceLocator locator) {
try {
String message = locator.getSystemId() + ":L" + locator.getLineNumber() + " : " + content.getTypedValue();
transformationLog.add(message);
// logger.info(message);
} catch (SaxonApiException e) {
// logger.error("", e);
}
}
}

/**
* Initialize the XSLT processor using the input XSL transformation document
*
* @param loadingScheme XSL transformation document
* @throws SaxonApiException if {@code XsltCompiler} failed to compile the input XSLT document. This exception
* occurs in case the input string is not a valid XSLT document.
*/
TransformXML(String loadingScheme) throws SaxonApiException {
/* if (StringUtils.isEmpty(loadingScheme)) {
loadingScheme = DEFAULT_LOADING_SCHEME_XSLT;
}*/
final boolean isLicensed = false;
processor = new Processor(isLicensed);
xsltCompiler = processor.newXsltCompiler();
xsltCompiler.setErrorListener(new ErrorListenerImpl());
xsltExecutable = xsltCompiler.compile(new StreamSource(new StringReader(loadingScheme)));
}

/**
* Transform input stream using reference product
*
* @param referenceProduct the XSLT input parameter
* @param inputStream input to transform
* @return the transformation result
* @throws IOException if failed to create a string writer
* @throws SaxonApiException if failed to transform the input stream
*/
public String transform(String referenceProduct, InputStream inputStream) throws IOException, SaxonApiException {
if (xsltTransformer == null) {
serializer = processor.newSerializer();
xsltTransformer = xsltExecutable.load();
xsltTransformer.setDestination(serializer);
xsltTransformer.setMessageListener(new MessageListenerImpl());
documentBuilder = processor.newDocumentBuilder();
XdmNode paramNode = documentBuilder.build(new StreamSource(new StringReader(referenceProduct)));
xsltTransformer.setParameter(new QName(REFERENCE_PRODUCT_PARAM_NAME), paramNode);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(baos); //("c:\\test\\output.xml");
StandardLogger theLogger = new StandardLogger(stream);
XSLTTraceListener traceListener = new XSLTTraceListener();
traceListener.setOutputDestination(theLogger);
xsltTransformer.setTraceListener(traceListener);
String result;
XdmNode contextNode = null;
try (StringWriter stringWriter = new StringWriter()) {
serializer.setOutputWriter(stringWriter);
contextNode = documentBuilder.build(new StreamSource(inputStream));
xsltTransformer.setInitialContextNode(contextNode);
xsltTransformer.transform();
String productDefinition = stringWriter.toString();

result = productDefinition ;//fillInProductDefinitionIterators(productDefinition);

} catch (SaxonApiException e) {
String message = getUserFriendlyMessage(e);
transformationLog.add(0, message);
throw e;
}
finally {
stream.flush();
stream.close();
}
return result;
}
/**
* Get a list of compilation errors and transformation debug messages of form {@code xsl:message}.
* Transformation warnings are not returned but are logged using the default system logger instead.
*
* @return the list of error and debug messages
*/
List<String> getTransformationLog() {
return transformationLog;
}

/**
* Fill-in all the product definition iterators with their default values
*
* @param productDefinition product definition XML
* @return the product definition with all the iterators set to their default values
* @throws IOException if failed to create a string writer
* @throws SaxonApiException if transformation failed
*/

/**
* Remove the exception class from the exception message for user-friendly presentation
*
* @param throwable exception to format
* @return the formatted exception message
*/
private String getUserFriendlyMessage(Throwable throwable) {
String result = throwable.getMessage().replaceFirst("^[\\w.]*;?\\s*", "");
return result;
}

public static void main(String[] args) {
try {
String referenceProductFileName = args[0];
byte[] refProdBytes = getBytes(referenceProductFileName);
String referenceProduct = new String(refProdBytes, "UTF-8");
String schemeFileName = args[1];
byte[] schemeBytes = getBytes(schemeFileName);
String scheme = new String(schemeBytes, "UTF-8");
String sourceXML = args[2];
byte[] sourceXMLBytes = getBytes(sourceXML);
ByteArrayInputStream inputStream = new ByteArrayInputStream(sourceXMLBytes);
TransformXML transformXML = new TransformXML(scheme);
transformXML.transform(referenceProduct, inputStream);
} catch (Exception e) {
// TODO Auto-generated catch block
//e.printStackTrace();
ByteArrayOutputStream errorBaos = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(errorBaos); //("c:\\test\\output.xml");
StandardLogger logger = new StandardLogger(stream);
if(e.getCause() instanceof net.sf.saxon.trans.XPathException) {
net.sf.saxon.trans.XPathException cause = (net.sf.saxon.trans.XPathException)e.getCause();
net.sf.saxon.lib.StandardErrorListener.printStackTrace(logger, cause.getXPathContext());
}else {
if(e.getCause() instanceof XPathException) {
ValidationException cause = (ValidationException)e.getCause();
net.sf.saxon.lib.StandardErrorListener.printStackTrace(logger, cause.getXPathContext());
}
}
try {
String errorText = errorBaos.toString("UTF8");
System.out.println("e.getCause(): " + e.getCause() + " \nerror text from StandardErrorListener:" + errorText);
} catch (UnsupportedEncodingException e1) {
}
}
}
public static byte[] getBytes(String fileName) throws IOException {
File file = new File(fileName);
byte[] imgDataBa = new byte[(int)file.length()];
DataInputStream dataIs = new DataInputStream(new FileInputStream(file));
dataIs.readFully(imgDataBa);
//dataIs.close();
return imgDataBa;
}
}
(1-1/2)