Skip to content

Commit

Permalink
Merge pull request #170 from metanorma/preprocess_xslt
Browse files Browse the repository at this point in the history
Preprocess xslt
  • Loading branch information
Intelligent2013 authored Dec 28, 2022
2 parents 07ccba2 + 651cf4d commit 31909a4
Show file tree
Hide file tree
Showing 6 changed files with 438 additions and 44 deletions.
31 changes: 11 additions & 20 deletions src/main/java/org/metanorma/fop/PDFGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,27 +271,17 @@ public boolean process() {

logger.info(String.format(OUTPUT_LOG, PDF_OUTPUT, fPDF));
logger.info("");

// read input XML to XML document and find tag '<review'
String element_review = Util.readValueFromXML(fXML, "//*[local-name() = 'review'][1]");
isAddAnnotations = element_review.length() != 0;

// find tag 'table' or 'dl'
String element_table = Util.readValueFromXML(fXML, "//*[local-name() = 'table' or local-name() = 'dl'][1]");
isTableExists = element_table.length() != 0;

String element_math = Util.readValueFromXML(fXML, "//*[local-name() = 'math'][1]");

// read XSL to XML Document and find param values
String add_math_as_text = Util.readValueFromXML(fXSL, "/*[local-name() = 'stylesheet']/*[local-name() = 'param'][@name = 'add_math_as_text']");
isAddMathAsText = add_math_as_text.equalsIgnoreCase("true") && element_math.length() != 0;

String add_math_as_attachment = Util.readValueFromXML(fXSL, "/*[local-name() = 'stylesheet']/*[local-name() = 'param'][@name = 'add_math_as_attachment']");
isAddMathAsAttachment = add_math_as_attachment.equalsIgnoreCase("true");


sourceXMLDocument = new SourceXMLDocument(fXML);

XSLTconverter xsltConverter = new XSLTconverter(fXSL);

isAddAnnotations = sourceXMLDocument.hasAnnotations();
isTableExists = sourceXMLDocument.hasTables();
boolean isMathExists = sourceXMLDocument.hasMath();

XSLTconverter xsltConverter = new XSLTconverter(fXSL, sourceXMLDocument.getPreprocessXSLT(), fPDF.getAbsolutePath());

isAddMathAsText = xsltConverter.hasParamAddMathAsText() && isMathExists;
isAddMathAsAttachment = xsltConverter.hasParamAddMathAsAttachment();

if (isSyntaxHighlight) {
xsltParams.put("syntax-highlight", "true");
Expand Down Expand Up @@ -342,6 +332,7 @@ public boolean process() {
// flush temporary folder
if (!DEBUG) {
sourceXMLDocument.flushTempPath();
xsltConverter.deleteTmpXSL();
}

logger.info("Success!");
Expand Down
111 changes: 101 additions & 10 deletions src/main/java/org/metanorma/fop/SourceXMLDocument.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package org.metanorma.fop;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -18,9 +13,9 @@
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.*;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
Expand All @@ -32,6 +27,8 @@
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import static org.metanorma.fop.PDFGenerator.logger;
import static org.metanorma.fop.Util.getStreamFromResources;

import org.metanorma.utils.LoggerHelper;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
Expand Down Expand Up @@ -280,7 +277,55 @@ public ArrayList<String> getLanguagesList () {

return languagesList;
}


public String getPreprocessXSLT() {

StringBuilder inlineXSLT = new StringBuilder();
try {

XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression query = xPath.compile("//*[contains(local-name(),'ogc-standard')]/*[local-name()='render']/*[local-name()='preprocess-xslt']/*[local-name()='stylesheet']");
NodeList nList = (NodeList)query.evaluate(sourceXML, XPathConstants.NODESET);

for (int i = 0; i < nList.getLength(); i++) {
Node nodeXSLT = nList.item(i);

// convert Node to Document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document documentXSLT = builder.newDocument();
Node importedNode = documentXSLT.importNode(nodeXSLT, true);
documentXSLT.appendChild(importedNode);

TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(documentXSLT), new StreamResult(writer));
String xslt = writer.getBuffer().toString();

documentXSLT = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xslt)));
String xsltUpdated = updatePreprocessXSLT(documentXSLT);
documentXSLT = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xsltUpdated)));

XPath xPath2 = XPathFactory.newInstance().newXPath();
XPathExpression query2 = xPath2.compile("/*"); // select all nodes inside xsl:stylesheet
NodeList nList2 = (NodeList)query2.evaluate(documentXSLT, XPathConstants.NODESET);

for (int j = 0; j < nList2.getLength(); j++) {
Node nodeXSLT2 = nList2.item(j);
inlineXSLT.append(Util.innerXml(nodeXSLT2));
}
}

} catch (Exception ex) {
logger.severe("Can't read pre-process XSLT from source XML.");
ex.printStackTrace();
}
return inlineXSLT.toString().replaceAll("xmlns=\"\"", "");
}

public void flushTempPath() {
if (Files.exists(tmpfilepath)) {

Expand All @@ -303,4 +348,50 @@ public String getTempPath() {
public String getDocumentFilePath() {
return documentFilePath;
}


private String updatePreprocessXSLT(Document docXML) throws Exception {

Source srcXSL = new StreamSource(getStreamFromResources(getClass().getClassLoader(), "update_preprocess_xslt.xsl"));
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(srcXSL);

StringWriter resultWriter = new StringWriter();
StreamResult sr = new StreamResult(resultWriter);
transformer.transform(new DOMSource(docXML), sr);
String xmlResult = resultWriter.toString();

return xmlResult;
}

private String readValue(String xpath) {
String value = "";
try {
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression query = xPath.compile(xpath);
Node textElement = (Node)query.evaluate(sourceXML, XPathConstants.NODE);
if(textElement != null) {
value = textElement.getTextContent();
}
} catch (Exception ex) {
logger.severe(ex.toString());
}
return value;
}

public boolean hasAnnotations() {
String element_review = readValue("//*[local-name() = 'review'][1]");
return element_review.length() != 0;
}

// find tag 'table' or 'dl'
public boolean hasTables() {
String element_table = readValue("//*[local-name() = 'table' or local-name() = 'dl'][1]");
return element_table.length() != 0;
}

public boolean hasMath() {
String element_math = readValue("//*[local-name() = 'math'][1]");
return element_math.length() != 0;
}
}
122 changes: 108 additions & 14 deletions src/main/java/org/metanorma/fop/XSLTconverter.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
package org.metanorma.fop;

import java.io.File;
import java.io.StringWriter;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import static org.metanorma.Constants.DEBUG;
import static org.metanorma.Constants.ERROR_EXIT_CODE;
import static org.metanorma.fop.PDFGenerator.logger;
import org.metanorma.utils.LoggerHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/**
*
Expand All @@ -28,7 +35,11 @@ public class XSLTconverter {
protected static final Logger logger = Logger.getLogger(LoggerHelper.LOGGER_NAME);

//private Properties xslparams = new Properties();


Document sourceXSLT;

File tmpfileXSL;

private Transformer transformerFO;

private long startTime;
Expand All @@ -37,21 +48,69 @@ public XSLTconverter(File fXSL) {

TransformerFactory factoryFO = TransformerFactory.newInstance();
try {
sourceXSLT = getDocument(fXSL);
transformerFO = factoryFO.newTransformer(new StreamSource(fXSL));
} catch (TransformerConfigurationException ex) {
ex.printStackTrace(System.err);
System.exit(ERROR_EXIT_CODE);
}

transformerFO.setOutputProperty(OutputKeys.ENCODING, "UTF-16"); // to fix issue with UTF-16 surrogate pairs

}


public XSLTconverter(File fXSL, String preprocessXSLT, String outPath) {
TransformerFactory factoryFO = TransformerFactory.newInstance();
try {
sourceXSLT = getDocument(fXSL);

if (!preprocessXSLT.isEmpty()) {
// content of fXSL file
String xsltString = new String(Files.readAllBytes(fXSL.toPath()));
String xsltEnd = "</xsl:stylesheet>";
// add preprocess XSLT at the end of main XSLT
xsltString = xsltString.replace(xsltEnd, preprocessXSLT + xsltEnd);

// SystemId Unknown; Line #0; Column #0; Unknown error in XPath.
// SystemId Unknown; Line #10648; Column #30; java.lang.NullPointerException
//transformerFO = factoryFO.newTransformer(new StreamSource(new StringReader(xsltString)));

// save XSLT to the file
String tmpXSL = outPath + ".xsl";
BufferedWriter writer = new BufferedWriter(new FileWriter(tmpXSL));
writer.write(xsltString);
writer.close();

tmpfileXSL = new File(tmpXSL);
transformerFO = factoryFO.newTransformer(new StreamSource(tmpfileXSL));
} else {
transformerFO = factoryFO.newTransformer(new StreamSource(fXSL));
}
} catch (TransformerConfigurationException | IOException ex) {
ex.printStackTrace(System.err);
System.exit(ERROR_EXIT_CODE);
}

transformerFO.setOutputProperty(OutputKeys.ENCODING, "UTF-16"); // to fix issue with UTF-16 surrogate pairs
}

public Transformer getTransformer ()
{
return transformerFO;
}


private Document getDocument (File file) {
Document doc;
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
InputStream xsltstream = new FileInputStream(file);
doc = dBuilder.parse(xsltstream);
return doc;
} catch (Exception ex) {
ex.printStackTrace(System.err);
System.exit(ERROR_EXIT_CODE);
}
return null;
}

public void setParams(Properties xslparams) {
//this.xslparams = xslparams;
Expand All @@ -62,7 +121,6 @@ public void setParams(Properties xslparams) {

transformerFO.setParameter(name, value);
}

}

public void setParam(String name, Object value) {
Expand Down Expand Up @@ -103,4 +161,40 @@ public void transform(SourceXMLDocument sourceXMLDocument, boolean isFinalTransf
Profiler.printProcessingTime(methodName, startTime);
Profiler.removeMethodCall();
}

private String readValue(String xpath) {
String value = "";
try {
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression query = xPath.compile(xpath);
Node textElement = (Node)query.evaluate(sourceXSLT, XPathConstants.NODE);
if(textElement != null) {
value = textElement.getTextContent();
}
} catch (Exception ex) {
logger.severe(ex.toString());
}
return value;
}

public boolean hasParamAddMathAsText() {
String param_add_math_as_text = readValue("/*[local-name() = 'stylesheet']/*[local-name() = 'param'][@name = 'add_math_as_text']");
return param_add_math_as_text.equalsIgnoreCase("true");
}

public boolean hasParamAddMathAsAttachment() {
String param_add_math_as_attachment = readValue("/*[local-name() = 'stylesheet']/*[local-name() = 'param'][@name = 'add_math_as_attachment']");
return param_add_math_as_attachment.equalsIgnoreCase("true");
}

public void deleteTmpXSL() {
if (tmpfileXSL != null) {
try {
Files.deleteIfExists(tmpfileXSL.toPath());
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}

}
Loading

0 comments on commit 31909a4

Please sign in to comment.