如何修复PDFBox设置的PDF / A元数据(与Docx4j和XDocReport一起使用)

时间:2019-02-05 11:37:39

标签: pdfbox apache-fop docx4j pdfa xdocreport

为了达到可访问性级别PDF / A-1A,我正在使用PDFBox v2.0.13在PDF上设置XMP元数据。在设置元数据之前,我将文件从.docx转换为pdf。我尝试了两种转换方法:一种使用XDocReport v.2.0.1,另一种使用Docx4j v.6.1.0。

在Java类中,我具有以下代码:

PDDocumentInformation info = pdf.getDocumentInformation();
info.setTitle("Apache PDFBox");
info.setSubject("Apache PDFBox adding meta-data to PDF document");
info.setCreator("MyCreator");
...
DublinCoreSchema dcSchema = metadata.createAndAddDublinCoreSchema();
dcSchema.setTitle(info.getTitle());
dcSchema.setDescription(info.getSubject());
dcSchema.addCreator(info.getCreator());

使用XDocReport进行转换,我得到以下元数据:

  </rdf:Description>
    <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
      <dc:title>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Apache PDFBox</rdf:li>
        </rdf:Alt>
      </dc:title>
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Apache PDFBox adding meta-data to PDF document</rdf:li>
        </rdf:Alt>
      </dc:description>
      <dc:creator>
        <rdf:Seq>
          <rdf:li>MyCreator</rdf:li>
        </rdf:Seq>
      </dc:creator>
   </rdf:Description>

我将使用以下元数据代替Docx4j进行转换:

    <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
      <dc:title>
        <rdf:Alt>
          <rdf:li lang="x-default">Apache PDFBox</rdf:li>
        </rdf:Alt>
      </dc:title>
      <dc:description>
        <rdf:Alt>
          <rdf:li lang="x-default">Apache PDFBox adding meta-data to PDF document</rdf:li>
        </rdf:Alt>
      </dc:description>
      <dc:creator>
        <rdf:Seq>
          <rdf:li>MyCreator</rdf:li>
        </rdf:Seq>
      </dc:creator>
    </rdf:Description>

由于为“标题”和“描述”生成的元数据不同,因此无法访问使用XDocReport结果PDF / A-1A生成的最终pdf,而无法访问使用Docx4j生成的最终pdf。

可访问性检查是使用VeraPDF进行的。

由于Docx4j生成了更具可读性的PDF,是否有办法将元数据固定在最终的pdf中?

2 个答案:

答案 0 :(得分:1)

docx4j的export-FO使用Apache FOP(v2.3)创建PDF。

因此export-FO具有与FOP v2.3相同的PDF / A-1A制作能力:https://xmlgraphics.apache.org/fop/2.3/pdfa.html

所以我尝试了:

    FOUserAgent foUserAgent = FORendererApacheFOP.getFOUserAgent(foSettings);       
    foUserAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");     
    // nb PDF/A-1a, PDF/A-2a and PDF/A-3a require accessibility to be enabled

但它抱怨:

For PDF/A-1b, all fonts, even the base 14 fonts, have to be embedded! Offending font: /Times-Roman
org.apache.fop.pdf.PDFConformanceException: For PDF/A-1b, all fonts, even the base 14 fonts, have to be embedded! Offending font: /Times-Roman
    at org.apache.fop.pdf.PDFFont.validate(PDFFont.java:170)

因此,您需要研究嵌入基本的14种字体。

作为旁注,我在使用export-FO创建的简单PDF上尝试了PDFBox的ExtractMetadata示例。不幸的是,它报告:

An error ouccred when parsing the meta data: Invalid array definition, expecting Alt and found com.sun.org.apache.xerces.internal.dom.DeferredTextImpl [prefix=dc; name=title]

作为所有替代方法,您可以考虑我们的商业PDF Converter。可以生成PDF / A-2b:https://converter-eval.plutext.com/pdf_archive.html

答案 1 :(得分:0)

当xmpbox与某些其他库一起使用时,这是一个已知的问题,例如FOP。

问题出在变压器上。

XmpSerializer.java中的这段代码:

Transformer transformer = TransformerFactory.newInstance().newTransformer();

应返回一个com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl类。 (尝试)

javadoc: https://docs.oracle.com/javase/7/docs/api/javax/xml/transform/TransformerFactory.html#newInstance()

“ Services API将在运行时可用的jar中的文件META-INF / services / javax.xml.transform.TransformerFactory中寻找类名。”

您可以通过设置系统属性来强制执行默认实现:

System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");

但是,这可能会使另一个库中的内容混乱。

另一种解决方案是复制XmpSerializer的源代码,并像这样更改newInstance调用:

Transformer transformer = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", null).newTransformer();

Source