Following on from this thread: https://sourceforge.net/p/ujac/discussion/255347/thread/c9c052f9/?limit=25
I think I've found an issue with entity references inside attributes and the supportToC flag.
The problem is that if an attribute contains an entity reference as part of it's value, PDF generation fails with the following error:
Exception in thread "main" Document processing failure at line 3:
org.ujac.print.DocumentHandlerException: The reference to entity "id" must end with the ';' delimiter.
at org.ujac.print.DocumentPrinter.printDocument(DocumentPrinter.java:647)
at org.ujac.print.DocumentPrinter.printDocument(DocumentPrinter.java:545)
at PDFTester.main(PDFTester.java:42)
Caused by:The reference to entity "id" must end with the ';' delimiter.
org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 145; The reference to entity "id" must end with the ';' delimiter.
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at org.ujac.util.xml.XMLReaderWrapper.parse(XMLReaderWrapper.java:77)
at org.ujac.print.DocumentPrinter.printDocument(DocumentPrinter.java:626)
at org.ujac.print.DocumentPrinter.printDocument(DocumentPrinter.java:545)
at PDFTester.main(PDFTester.java:42)
I believe this is caused by the following code
DocumentHandler.java - Line 1949
try {
if (templateCopyWriter != null) {
// copying template for later use
templateCopyWriter.write('<');
templateCopyWriter.print(localName);
int numAttribs = attributes.getLength();
for (int i = 0; i < numAttribs; i++) {
templateCopyWriter.write(' ');
templateCopyWriter.print(attributes.getLocalName(i));
templateCopyWriter.print("=\"");
templateCopyWriter.print(attributes.getValue(i));
templateCopyWriter.write('\"');
}
templateCopyWriter.write('>');
}
I believe the issue stems from attributes.getValue(i), which has removed the entity references, and writes them back to the temporary file in their un-encoded format.
The simplest example I could make is below.
Sample XML
<document size="A4">
<image width="140" scale-to-fit="true" source="https://www.google.co.uk/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png?dummy=1&id=1"/>
</document>
Java to Generate PDF
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import org.apache.commons.io.IOUtils;
import org.ujac.print.DocumentHandlerException;
import org.ujac.print.DocumentPrinter;
import org.ujac.util.exi.ExpressionInterpreter;
import org.ujac.util.io.HttpResourceLoader;
import org.ujac.util.template.DefaultTemplateInterpreter;
public class PDFTester {
private static class NullTemplateInterpreter extends DefaultTemplateInterpreter {
public NullTemplateInterpreter() {
super(ExpressionInterpreter.createInstance());
this.tokenTypes = new HashMap();
}
}
public static void main(String[] args) throws DocumentHandlerException, IOException{
File inputfile = new File("C:\\Users\\...\\Desktop\\test.xml");
FileInputStream fis = new FileInputStream(inputfile);
//create a new converter using the stream from the xmltemplate
DocumentPrinter pdfcreator = new DocumentPrinter(fis, new HashMap());
//set the resource loader to use url resource loading
pdfcreator.setResourceLoader(new HttpResourceLoader());
//set the template interpreter to ignore all template tags
pdfcreator.setTemplateInterpreter(new NullTemplateInterpreter());
//create an in memory output stream to create the pdf
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//print the pdf to the pdf output stream
//toggling this to false generates the PDF correctly
pdfcreator.printDocument(baos,true);
FileOutputStream fileOut = new FileOutputStream("C:\\Users\\...\\Desktop\\result.pdf");
//copy the in memory stream to the servlet output stream
IOUtils.copy(new ByteArrayInputStream(baos.toByteArray()), fileOut);
}
}
Temporary File Contents
<?xml version="1.0" encoding="UTF-8"?>
<document size="A4">
<image width="140" scale-to-fit="true" source="https://www.google.co.uk/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png?dummy=1&id=1"></image>
</document>
As you can see above, the value of the source attribute in the temporary file hsa had the "&" replaces with "&". When this is read back in by the parser it attempts to treat "&id" as an entity reference, but fails to find a semi-colon so throws an exception.
I believe the call to attributes.getValue(i) needs to be xml encoded in some way.