creating pdf/a files using this config file:<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="11in" width="8.26in"/>

  <!-- etc. etc..... -->

  <renderers>
   <renderer mime="application/pdf">
   <fonts>
       <font kerning="no" embed-url="file:///C:/Users/jstaerk/temp/timesbd.ttf" embedding-mode="subset">
           <font-triplet name="Times" style="normal" weight="bold" />
       </font>
       <font kerning="no" embed-url="file:///C:/Users/jstaerk/temp/timesbd.ttf" embedding-mode="subset">
           <font-triplet name="SourceSerifPro" style="normal" weight="normal" />
       </font>
   </fonts>
   </renderer>
</renderers>

</fop>
This commit is contained in:
jstaerk
2023-07-26 20:23:56 +02:00
parent 412a17166f
commit 3e81c7036f
2 changed files with 211 additions and 33 deletions

View File

@@ -1,21 +1,23 @@
/** **********************************************************************
*
/**
* *********************************************************************
* <p>
* Copyright 2018 Jochen Staerk
*
* <p>
* Use is subject to license terms.
*
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
*
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* <p>
* See the License for the specific language governing permissions and
* limitations under the License.
*
*********************************************************************** */
* <p>
* **********************************************************************
*/
package org.mustangproject.ZUGFeRD;
import javax.xml.transform.*;
@@ -36,6 +38,7 @@ public class ZUGFeRDVisualizer {
FR,
DE
}
static final ClassLoader CLASS_LOADER = ZUGFeRDVisualizer.class.getClassLoader();
private static final String RESOURCE_PATH = "";
private static final Logger LOG = Logger.getLogger(ZUGFeRDVisualizer.class.getName());
@@ -54,6 +57,7 @@ public class ZUGFeRDVisualizer {
private Templates mXsltXRTemplate = null;
private Templates mXsltUBLTemplate = null;
private Templates mXsltHTMLTemplate = null;
private Templates mXsltPDFTemplate = null;
private Templates mXsltZF1HTMLTemplate = null;
public ZUGFeRDVisualizer() {
@@ -66,13 +70,19 @@ public class ZUGFeRDVisualizer {
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
try {
if (mXsltXRTemplate==null) {
if (mXsltXRTemplate == null) {
mXsltXRTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
}
mXsltHTMLTemplate = mFactory.newTemplates(new StreamSource(
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xrechnung-html."+lang.name().toLowerCase()+".xsl")));
if (mXsltZF1HTMLTemplate==null) {
if (mXsltPDFTemplate == null) {
mXsltPDFTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
}
if (mXsltHTMLTemplate == null) {
mXsltHTMLTemplate = mFactory.newTemplates(new StreamSource(
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xrechnung-html." + lang.name().toLowerCase() + ".xsl")));
}
if (mXsltZF1HTMLTemplate == null) {
mXsltZF1HTMLTemplate = mFactory.newTemplates(new StreamSource(
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt")));
}
@@ -86,14 +96,14 @@ public class ZUGFeRDVisualizer {
* http://www.ferd-net.de/upload/Dokumente/FACTUR-X_ZUGFeRD_2p0_Teil1_Profil_EN16931_1p03.pdf
* http://countwordsfree.com/xmlviewer
*/
FileInputStream fis=new FileInputStream(xmlFilename);
String fileContent="";
FileInputStream fis = new FileInputStream(xmlFilename);
String fileContent = "";
try {
fileContent = new String(Files.readAllBytes(Paths.get(xmlFilename)), StandardCharsets.UTF_8);
} catch (IOException e2) {
LOG.log(Level.SEVERE, null, e2);
}
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -101,7 +111,7 @@ public class ZUGFeRDVisualizer {
String zf2Signature = "rsm:CrossIndustryInvoice";
String ublSignature = "ubl:Invoice";
String ublCreditNoteSignature = "ubl:CreditNote";
boolean doPostProcessing=false;
boolean doPostProcessing = false;
if (fileContent.contains(zf1Signature)) {
applyZF1XSLT(fis, baos);
@@ -109,16 +119,16 @@ public class ZUGFeRDVisualizer {
//zf2 or fx
applyZF2XSLT(fis, iaos);
doPostProcessing=true;
doPostProcessing = true;
} else if (fileContent.contains(ublSignature)) {
//zf2 or fx
applyUBL2XSLT(fis, iaos);
doPostProcessing=true;
doPostProcessing = true;
} else if (fileContent.contains(ublCreditNoteSignature)) {
//zf2 or fx
applyUBLCreditNote2XSLT(fis, iaos);
doPostProcessing=true;
doPostProcessing = true;
}
if (doPostProcessing) {
@@ -158,20 +168,88 @@ public class ZUGFeRDVisualizer {
}
}
return baos.toString("UTF-8");
}
public void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
public String toFOP(String xmlFilename)
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
try {
if (mXsltXRTemplate == null) {
mXsltXRTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
}
if (mXsltPDFTemplate == null) {
mXsltPDFTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
}
} catch (TransformerConfigurationException ex) {
LOG.log(Level.SEVERE, null, ex);
}
FileInputStream fis = new FileInputStream(xmlFilename);
String fileContent = "";
try {
fileContent = new String(Files.readAllBytes(Paths.get(xmlFilename)), StandardCharsets.UTF_8);
} catch (IOException e2) {
LOG.log(Level.SEVERE, null, e2);
}
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//zf2 or fx
applyZF2XSLT(fis, iaos);
PipedInputStream in = new PipedInputStream();
PipedOutputStream out;
try {
out = new PipedOutputStream(in);
new Thread(new Runnable() {
public void run() {
try {
// write the original OutputStream to the PipedOutputStream
// note that in order for the below method to work, you need
// to ensure that the data has finished writing to the
// ByteArrayOutputStream
iaos.writeTo(out);
} catch (IOException e) {
LOG.log(Level.SEVERE, null, e);
} finally {
// close the PipedOutputStream here because we're done writing data
// once this thread has completed its run
if (out != null) {
// close the PipedOutputStream cleanly
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
LOG.log(Level.SEVERE, null, e);
}
}
}
}
}).start();
applyXSLTToPDF(in, baos);
} catch (IOException e1) {
LOG.log(Level.SEVERE, null, e1);
}
return baos.toString("UTF-8");
}
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
Transformer transformer = mXsltXRTemplate.newTransformer();
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
}
public void applyUBL2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
protected void applyUBL2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
if (mXsltUBLTemplate==null) {
if (mXsltUBLTemplate == null) {
mXsltUBLTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ubl-invoice-xr.xsl")));
}
@@ -180,9 +258,9 @@ public class ZUGFeRDVisualizer {
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
}
public void applyUBLCreditNote2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
protected void applyUBLCreditNote2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
if (mXsltUBLTemplate==null) {
if (mXsltUBLTemplate == null) {
mXsltUBLTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ubl-creditnote-xr.xsl")));
}
@@ -191,20 +269,27 @@ public class ZUGFeRDVisualizer {
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
}
public void applyZF1XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
protected void applyZF1XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
Transformer transformer = mXsltZF1HTMLTemplate.newTransformer();
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
}
public void applyXSLTToHTML(final InputStream xmlFile, final OutputStream HTMLOutstream)
protected void applyXSLTToHTML(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
Transformer transformer = mXsltHTMLTemplate.newTransformer();
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
}
protected void applyXSLTToPDF(final InputStream xmlFile, final OutputStream PDFOutstream)
throws TransformerException {
Transformer transformer = mXsltPDFTemplate.newTransformer();
transformer.transform(new StreamSource(xmlFile), new StreamResult(PDFOutstream));
}
private static class ClasspathResourceURIResolver implements URIResolver {
ClasspathResourceURIResolver() {
// Do nothing, just prevents synthetic access warning.
@@ -212,7 +297,7 @@ public class ZUGFeRDVisualizer {
@Override
public Source resolve(String href, String base) throws TransformerException {
return new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH +"stylesheets/"+ href));
return new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/" + href));
}
}
}

View File

@@ -19,17 +19,23 @@
*********************************************************************** */
package org.mustangproject.ZUGFeRD;
import org.apache.fop.apps.FOPException;
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.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import org.mustangproject.CII.CIIToUBL;
import org.xml.sax.SAXException;
import javax.xml.transform.TransformerException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.xml.transform.*;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class VisualizationTest extends ResourceCase {
@@ -141,4 +147,91 @@ public class VisualizationTest extends ResourceCase {
// Reading ZUGFeRD
assertEquals(expected, result);
}
public void testPDFVisualization() {
// the writing part
CIIToUBL c2u = new CIIToUBL();
String sourceFilename = "factur-x.xml";
File CIIinputFile = getResourceAsFile(sourceFilename);
String expected = null;
String result = null;
try {
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)
*/
result = zvi.toFOP(CIIinputFile.getAbsolutePath());
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) {
fail("UnsupportedOperationException should not happen: "+e.getMessage());
} catch (IllegalArgumentException e) {
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);
// Reading ZUGFeRD
assertEquals(expected, result);
}
}