attempt to be able to convert to pdf
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
2.8.0
|
||||||
|
=======
|
||||||
|
|
||||||
|
Improvement of included notes #331
|
||||||
|
|
||||||
2.7.3
|
2.7.3
|
||||||
=======
|
=======
|
||||||
2023-06-16
|
2023-06-16
|
||||||
|
|||||||
3
NOTICE
3
NOTICE
@@ -33,3 +33,6 @@ Based on https://jcthiele.github.io/xrechnung-visualization-codelist-resolve/ un
|
|||||||
Based on Saxon-HE https://sourceforge.net/projects/saxon/ licensed under the MPL 2.0
|
Based on Saxon-HE https://sourceforge.net/projects/saxon/ licensed under the MPL 2.0
|
||||||
Based on DOM4j https://dom4j.github.io/ licensed under the BSD license
|
Based on DOM4j https://dom4j.github.io/ licensed under the BSD license
|
||||||
Based on EN16931 validation artefacts https://github.com/ConnectingEurope/eInvoicing-EN16931 licensed under the EUPL 2.0
|
Based on EN16931 validation artefacts https://github.com/ConnectingEurope/eInvoicing-EN16931 licensed under the EUPL 2.0
|
||||||
|
Based on https://xmlgraphics.apache.org/fop under the APL2.0
|
||||||
|
Based on https://github.com/saucecontrol/Compact-ICC-Profiles/ under the Public Domain
|
||||||
|
http://ftp.gnu.org/gnu/freefont/
|
||||||
|
|||||||
@@ -63,6 +63,12 @@
|
|||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>2.14.2</version>
|
<version>2.14.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.xmlgraphics</groupId>
|
||||||
|
<artifactId>fop</artifactId>
|
||||||
|
<version>2.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.activation</groupId>
|
<groupId>javax.activation</groupId>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.mustangproject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.apache.fop.apps.io.ResourceResolverFactory;
|
||||||
|
import org.apache.xmlgraphics.io.Resource;
|
||||||
|
import org.apache.xmlgraphics.io.ResourceResolver;
|
||||||
|
|
||||||
|
public class ClasspathResolverURIAdapter implements ResourceResolver {
|
||||||
|
|
||||||
|
private final ResourceResolver wrapped;
|
||||||
|
|
||||||
|
|
||||||
|
public ClasspathResolverURIAdapter() {
|
||||||
|
this.wrapped = ResourceResolverFactory.createDefaultResourceResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource getResource(URI uri) throws IOException {
|
||||||
|
if (uri.getScheme().equals("classpath")) {
|
||||||
|
URL url = getClass().getClassLoader().getResource(uri.getSchemeSpecificPart());
|
||||||
|
|
||||||
|
return new Resource(url.openStream());
|
||||||
|
} else {
|
||||||
|
return wrapped.getResource(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream getOutputStream(URI uri) throws IOException {
|
||||||
|
return wrapped.getOutputStream(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,11 +20,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
import org.apache.fop.apps.*;
|
||||||
|
import org.apache.fop.configuration.Configuration;
|
||||||
|
import org.apache.fop.configuration.ConfigurationException;
|
||||||
|
import org.apache.fop.configuration.DefaultConfigurationBuilder;
|
||||||
|
import org.apache.xmlgraphics.util.MimeConstants;
|
||||||
|
import org.mustangproject.CII.CIIToUBL;
|
||||||
|
import org.mustangproject.ClasspathResolverURIAdapter;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import javax.xml.transform.*;
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.sax.SAXResult;
|
||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
import javax.xml.transform.stream.StreamSource;
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -172,7 +184,7 @@ public class ZUGFeRDVisualizer {
|
|||||||
return baos.toString("UTF-8");
|
return baos.toString("UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toFOP(String xmlFilename)
|
protected String toFOP(String xmlFilename)
|
||||||
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
|
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -240,6 +252,99 @@ public class ZUGFeRDVisualizer {
|
|||||||
return baos.toString("UTF-8");
|
return baos.toString("UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void toPDF(String xmlFilename, String pdfFilename) {
|
||||||
|
|
||||||
|
// the writing part
|
||||||
|
CIIToUBL c2u = new CIIToUBL();
|
||||||
|
String sourceFilename = "factur-x.xml";
|
||||||
|
File CIIinputFile = new File(xmlFilename);
|
||||||
|
|
||||||
|
String expected = null;
|
||||||
|
String result = null;
|
||||||
|
|
||||||
|
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
||||||
|
/* remove file endings so that tests can also pass after checking
|
||||||
|
out from git with arbitrary options (which may include CSRF changes)
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
result = zvi.toFOP(CIIinputFile.getAbsolutePath());
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
} catch (TransformerException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
FopConfParser parser = null;
|
||||||
|
try {
|
||||||
|
//parsing configuration
|
||||||
|
parser = new FopConfParser(CLASS_LOADER.getResourceAsStream("fop-config.xconf"), new URI("file:///"));
|
||||||
|
|
||||||
|
} catch (SAXException e) {
|
||||||
|
throw new UncheckedIOException(new IOException(e));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
}*/
|
||||||
|
// FopFactoryBuilder builder = parser.getFopFactoryBuilder();
|
||||||
|
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
|
||||||
|
|
||||||
|
Configuration cfg = null;
|
||||||
|
try {
|
||||||
|
cfg = cfgBuilder.build(CLASS_LOADER.getResourceAsStream("fop-config.xconf"));
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
FopFactoryBuilder builder = new FopFactoryBuilder(new File(".").toURI(), new ClasspathResolverURIAdapter()).setConfiguration(cfg);
|
||||||
|
// Step 1: Construct a FopFactory by specifying a reference to the configuration file
|
||||||
|
// (reuse if you plan to render multiple documents!)
|
||||||
|
|
||||||
|
FopFactory fopFactory = builder.build();//FopFactory.newInstance(new File("c:\\Users\\jstaerk\\temp\\fop-config.xconf"));
|
||||||
|
|
||||||
|
FOUserAgent userAgent = fopFactory.newFOUserAgent();
|
||||||
|
|
||||||
|
userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");
|
||||||
|
|
||||||
|
// Step 2: Set up output stream.
|
||||||
|
// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
|
||||||
|
|
||||||
|
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(pdfFilename))) {
|
||||||
|
|
||||||
|
// Step 3: Construct fop with desired output format
|
||||||
|
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
|
||||||
|
|
||||||
|
// Step 4: Setup JAXP using identity transformer
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = factory.newTransformer(); // identity transformer
|
||||||
|
|
||||||
|
// Step 5: Setup input and output for XSLT transformation
|
||||||
|
// Setup input stream
|
||||||
|
Source src = new StreamSource(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
|
||||||
|
// Resulting SAX events (the generated FO) must be piped through to FOP
|
||||||
|
Result res = new SAXResult(fop.getDefaultHandler());
|
||||||
|
|
||||||
|
// Step 6: Start XSLT transformation and FOP processing
|
||||||
|
transformer.transform(src, res);
|
||||||
|
|
||||||
|
//Files.write(Paths.get("C:\\Users\\jstaerk\\temp\\fop.pdf"), res.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
} catch (FOPException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
} catch (TransformerConfigurationException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
} catch (TransformerException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||||
throws TransformerException {
|
throws TransformerException {
|
||||||
Transformer transformer = mXsltXRTemplate.newTransformer();
|
Transformer transformer = mXsltXRTemplate.newTransformer();
|
||||||
|
|||||||
BIN
library/src/main/resources/AdobeCompat-v2.icc
Normal file
BIN
library/src/main/resources/AdobeCompat-v2.icc
Normal file
Binary file not shown.
BIN
library/src/main/resources/FreeSans.ttf
Normal file
BIN
library/src/main/resources/FreeSans.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/FreeSerif.ttf
Normal file
BIN
library/src/main/resources/FreeSerif.ttf
Normal file
Binary file not shown.
37
library/src/main/resources/fop-config.xconf
Normal file
37
library/src/main/resources/fop-config.xconf
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<fop version="1.0">
|
||||||
|
|
||||||
|
<!-- Strict user configuration -->
|
||||||
|
<strict-configuration>true</strict-configuration>
|
||||||
|
|
||||||
|
<!-- Strict FO validation -->
|
||||||
|
<strict-validation>true</strict-validation>
|
||||||
|
|
||||||
|
<!-- Base URL for resolving relative URLs -->
|
||||||
|
<base>./</base>
|
||||||
|
|
||||||
|
<!-- Font Base URL for resolving relative font URLs -->
|
||||||
|
<font-base>./</font-base>
|
||||||
|
|
||||||
|
<!-- Source resolution in dpi (dots/pixels per inch) for determining the size of pixels in SVG and bitmap images, default: 72dpi -->
|
||||||
|
<source-resolution>72</source-resolution>
|
||||||
|
<!-- Target resolution in dpi (dots/pixels per inch) for specifying the target resolution for generated bitmaps, default: 72dpi -->
|
||||||
|
<target-resolution>72</target-resolution>
|
||||||
|
|
||||||
|
<!-- default page-height and page-width, in case
|
||||||
|
value is specified as auto -->
|
||||||
|
<default-page-settings height="297mm" width="210mm"/><!-- DIN A/4 -->
|
||||||
|
|
||||||
|
<!-- etc. etc..... -->
|
||||||
|
|
||||||
|
<renderers>
|
||||||
|
<renderer mime="application/pdf">
|
||||||
|
<fonts>
|
||||||
|
<font kerning="no" embed-url="file:///C:\Users\jstaerk\workspace\mustangproject\library\src\main\resources\FreeSans.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSerifPro" style="normal" weight="normal" />
|
||||||
|
</font>
|
||||||
|
</fonts>
|
||||||
|
<output-profile>classpath:AdobeCompat-v2.icc</output-profile>
|
||||||
|
</renderer>
|
||||||
|
</renderers>
|
||||||
|
|
||||||
|
</fop>
|
||||||
@@ -19,10 +19,7 @@
|
|||||||
*********************************************************************** */
|
*********************************************************************** */
|
||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
import org.apache.fop.apps.FOPException;
|
import org.apache.fop.apps.*;
|
||||||
import org.apache.fop.apps.FOUserAgent;
|
|
||||||
import org.apache.fop.apps.Fop;
|
|
||||||
import org.apache.fop.apps.FopFactory;
|
|
||||||
import org.apache.xmlgraphics.util.MimeConstants;
|
import org.apache.xmlgraphics.util.MimeConstants;
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
import org.junit.runners.MethodSorters;
|
import org.junit.runners.MethodSorters;
|
||||||
@@ -35,7 +32,6 @@ import javax.xml.transform.stream.StreamSource;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
public class VisualizationTest extends ResourceCase {
|
public class VisualizationTest extends ResourceCase {
|
||||||
@@ -162,76 +158,16 @@ public class VisualizationTest extends ResourceCase {
|
|||||||
/* remove file endings so that tests can also pass after checking
|
/* remove file endings so that tests can also pass after checking
|
||||||
out from git with arbitrary options (which may include CSRF changes)
|
out from git with arbitrary options (which may include CSRF changes)
|
||||||
*/
|
*/
|
||||||
result = zvi.toFOP(CIIinputFile.getAbsolutePath());
|
zvi.toPDF(CIIinputFile.getAbsolutePath(), "c:\\users\\jstaerk\\temp\\fopy2.pdf");
|
||||||
File expectedResult=getResourceAsFile("fop.xml");
|
|
||||||
ByteArrayOutputStream fopout = new ByteArrayOutputStream();
|
|
||||||
//FileOutputStream outfile = new FileOutputStream("c:\\Users\\jstaerk\\temp\\fop2.pdf");
|
|
||||||
// File out=new File("c:\\Users\\jstaerk\\temp\\fop.xml");
|
|
||||||
|
|
||||||
// Step 1: Construct a FopFactory by specifying a reference to the configuration file
|
|
||||||
// (reuse if you plan to render multiple documents!)
|
|
||||||
FopFactory fopFactory = FopFactory.newInstance(new File("c:\\Users\\jstaerk\\temp\\fop.xconf"));
|
|
||||||
FOUserAgent userAgent = fopFactory.newFOUserAgent();
|
|
||||||
userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");
|
|
||||||
|
|
||||||
// Step 2: Set up output stream.
|
|
||||||
// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
|
|
||||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("c:\\Users\\jstaerk\\temp\\fop3.pdf")));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Step 3: Construct fop with desired output format
|
|
||||||
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
|
|
||||||
|
|
||||||
// Step 4: Setup JAXP using identity transformer
|
|
||||||
TransformerFactory factory = TransformerFactory.newInstance();
|
|
||||||
Transformer transformer = factory.newTransformer(); // identity transformer
|
|
||||||
|
|
||||||
// Step 5: Setup input and output for XSLT transformation
|
|
||||||
// Setup input stream
|
|
||||||
Source src = new StreamSource(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
|
|
||||||
|
|
||||||
// Resulting SAX events (the generated FO) must be piped through to FOP
|
|
||||||
Result res = new SAXResult(fop.getDefaultHandler());
|
|
||||||
|
|
||||||
// Step 6: Start XSLT transformation and FOP processing
|
|
||||||
transformer.transform(src, res);
|
|
||||||
|
|
||||||
//Files.write(Paths.get("C:\\Users\\jstaerk\\temp\\fop.pdf"), res.toString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
//Clean-up
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, fopout);
|
|
||||||
/*
|
|
||||||
Transformer transformer = TransformerFactory.newInstance().newTransformer(
|
|
||||||
new StreamSource(new File(args[1])));
|
|
||||||
transformer.transform(new StreamSource(new File(args[0])),
|
|
||||||
new SAXResult(((Fop) fop).getDefaultHandler()));
|
|
||||||
*/
|
|
||||||
// fopout.toByteArray();
|
|
||||||
|
|
||||||
expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8).replace("\r","").replace("\n","");
|
|
||||||
// remove linebreaks as well...
|
|
||||||
|
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
fail("UnsupportedOperationException should not happen: "+e.getMessage());
|
fail("UnsupportedOperationException should not happen: "+e.getMessage());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
fail("IllegalArgumentException should not happen: "+e.getMessage());
|
fail("IllegalArgumentException should not happen: "+e.getMessage());
|
||||||
} catch (TransformerException e) {
|
|
||||||
fail("TransformerException should not happen: "+e.getMessage());
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("IOException should not happen: "+e.getMessage());
|
|
||||||
} catch (FOPException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SAXException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(result);
|
// assertNotNull(result);
|
||||||
// Reading ZUGFeRD
|
// Reading ZUGFeRD
|
||||||
assertEquals(expected, result);
|
// assertEquals(expected, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
library/src/test/resources/fop.fo
Normal file
1
library/src/test/resources/fop.fo
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user