3.30. XMP-Daten

Überblick

XMP steht für Extensible Metadata Platform und ist ein von Adobe initiierter offener Standard, Metadaten in beliebige Dateitypen einzubetten. Nicht nur PDF-Dokumente, auch Bilder können Informationen über den Ort, das Format und andere Daten über Daten einbinden.

Die Metadaten in PDF sind für die Weiterverarbeitung durch andere Programme wichtig und sollten daher richtig sein. Zum Testen bietet PDFUnit die gleichen Tags an, wie für XFA-Daten:

<!-- Tags to test XMP data: -->

<hasXMPData   />
<hasNoXMPData />

<!-- Inner tags of hasXMPData: -->

<hasXMPData>
  <matchingXPath />  (optional)
  <matchingXML   />  (optional)
  <withNode      />  (optional)
</hasXMPData>

Existenz und Abwesenheit von XMP

Die nächsten Beispiele zeigen die Prüfung der An- bzw. Abwesenheit von XMP-Daten:

<testcase name="hasXMPData">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData />
  </assertThat>
</testcase>
<testcase name="hasNoXMPData">
  <assertThat testDocument="xmp/bookmarkWithURLAction_noXMP.pdf">
    <hasNoXMPData />
  </assertThat>
</testcase>

Vergleich gegen eine XML-Datei

Mit dem Hilfsprogramm ExtractXMPData können die XMP-Daten eines PDF-Dokumentes in eine XML-Datei exportiert werden. XMP-Daten eines PDF-Dokumentes können dann gegen diese XML-Datei verglichen werden:

<testcase name="hasXMPData_MatchingXML">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <matchingXML file="xmp/metadata-added.xml" /> 1
    </hasXMPData>
  </assertThat>
</testcase>

1

Beim Vergleich zweier XML-Strukturen werden Leerzeichen ignoriert.

Einzelne XML-Tags validieren

XMP-Daten eines PDF-Dokumentes können gezielt auf einzelne XML-Knoten und ihren Wert überprüft werden. Das nächste Beispiel basiert auf dem folgenden XML-Ausschnitt:

<x:xmpmeta xmlns:x="adobe:ns:meta/">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    ...
    <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
      <xmp:CreateDate>2011-02-08T15:04:19+01:00</xmp:CreateDate>
      <xmp:ModifyDate>2011-02-08T15:04:19+01:00</xmp:ModifyDate>
      <xmp:CreatorTool>My program using iText</xmp:CreatorTool>
    </rdf:Description>
    ...
  </rdf:RDF>
</x:xmpmeta>

Für den Test auf einen Knoten aus den XMP-Daten steht das Tag <withNode /> zur Verfügung. Nachfolgend wird die Existenz zweier Knotens geprüft:

<testcase name="hasXMPData_WithNode_ValidateExistence">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <withNode name="xmp:CreateDate" />
      <withNode name="xmp:ModifyDate" />
    </hasXMPData>
  </assertThat>
</testcase>

Soll auch der Wert eines Knotens überprüft werden, muss der erwartete Wert im Attribut value=".." angegeben werden:

<!-- 
  When the node name occurs multiple times in the document, only
  the first node will be returned.
-->
<testcase name="hasXMPData_WithNodeAndValue">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <withNode name="xmp:CreateDate" value="2011-02-08T15:04:19+01:00" />
      <withNode name="xmp:ModifyDate" value="2011-02-08T15:04:19+01:00" />
    </hasXMPData>
  </assertThat>
</testcase>

Existiert ein gesuchter Knoten mehrfach innerhalb der XMP-Daten, wird der erste Treffer verwendet.

Der XPath-Ausdruck für den Knoten darf die Wurzel (document root) nicht enthalten, weil PDFUnit intern // ergänzt.

Der Knoten darf selbstverständlich auch ein Attribut-Knoten sein.

XPath-basierte XMP-Tests

Mit dem Tag <matchingXPath /> kann das ganze Potential von XPath genutzt werden:

<testcase name="hasXMPData_MatchingXPath_CreateDateWithValue">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <matchingXPath expr="//xmp:CreateDate[node() = '2011-02-08T15:04:19+01:00']" />
    </hasXMPData>
  </assertThat>
</testcase>
<testcase name="hasXMPData_MatchingXPath_MultipleInvocation">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <matchingXPath expr="count(//xmp:CreateDate) = 1" />
      <matchingXPath 
         expr="count(//xmp:CreateDate[1][node()='2011-02-08T15:04:19+01:00']) = 1" />
    </hasXMPData>
  </assertThat>
</testcase>

Der Funktionsumfang der Verarbeitung der XPath-Ausdrücke hängt vom verwendeten XML-Parser bzw. der XPath-Engine ab. PDFUnit verwendet die des JDK/JRE und unterliegt damit den Unterschieden der unterschiedlichen JVM-Hersteller.

Default-Namensraum in XPath

Wie schon für XFA-Tests beschrieben, werden XML-Namensräume automatisch ermittelt. Default-Namensräume müssen vorgegeben werden, weil sie im XML-Dokument mehrfach auftreten können und deshalb nicht aus dem Dokument abgeleitet werden können.

Hier die Verwendung des Default-Namensraumes für das Tag <matchingXPath />:

<testcase name="hasXMPData_MatchingXPath_WithDefaultNamespace">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <matchingXPath expr="//foo:format = 'application/pdf'"
                     defaultNamespace="http://purl.org/dc/elements/1.1/"
      />
    </hasXMPData>
  </assertThat>
</testcase>

Und noch ein Beispiel für den Default-Namensraum im Tag <withNode /> mit einem Erwartungswert:

<testcase name="hasXMPData_WithDefaultNamespace_XMLNode">
  <assertThat testDocument="xmp/metadata-added.pdf">
    <hasXMPData>
      <withNode name="foo:ModifyDate" 
                value="2011-02-08T15:04:19+01:00" 
                defaultNamespace="http://ns.adobe.com/xap/1.0/"
      />
    </hasXMPData>
  </assertThat>
</testcase>