Zurück |  | Weiter

## 3.29. XFA Daten

### Überblick

Die „XML Forms Architecture, (XFA)“ ist eine Erweiterung der PDF-Strukturen um XML-Informationen, mit dem Ziel, PDF-Formulare in den Prozessen eines Workflow's besser verarbeiten zu können.

XFA Formulare sind nicht kompatibel zu „AcroForms“. Deshalb sind die PDFUnit-Tests für Acroforms auch nicht verwendbar. Test auf XFA-Daten basieren überwiegend auf XPath:

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

    <hasXFAData   />
    <hasNoXFAData />

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

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

### Existenz und Abwesenheit von XFA

Der erste Test zielt auf die reine Existenz von XFA-Daten:

    <testcase name="hasXFAData">
      <assertThat testDocument="xfa/xfa-movie.pdf">
        <hasXFAData />
      </assertThat>
    </testcase>

Es ist auch möglich, explizit zu testen, dass ein PDF-Dokument keine XFA-Daten enthält:

    <testcase name="hasNoXFAData">
      <assertThat testDocument="xfa/no-xfa.pdf">
        <hasNoXFAData />
      </assertThat>
    </testcase>

### Vergleich gegen eine XML-Datei

Die XFA-Daten eines PDF-Dokumentes können mit dem Hilfsprogramm `ExtractXFAData` in eine XML-Datei exportiert werden. Diese Datei kann vollständig mit den XFA-Daten eines PDF-Dokumentes verglichen werden:

    <testcase name="hasXFAData_MatchingXML">
      <assertThat testDocument="xfa/xfa-movie.pdf">
        <hasXFAData>
          <matchingXML file="xfa/xfa-movie.xml" />
        </hasXFAData>
      </assertThat>
    </testcase>

| Whitespaces werden beim Vergleich der XML-Daten nicht berücksichtigt.

Oftmals ist es nicht sinnvoll, die kompletten XFA-Daten eines PDF-Dokumentes gegen eine XML-Vorlage zu vergleichen. Für solche Fälle gibt es sowohl die Möglichkeit, auf einzelne XML-Knoten zu testen, als auch Tests mit XPath-Ausdrücken zu formulieren. Beide Möglichkeiten werden in den folgenden Abschnitten beschrieben.

### Einzelne XML-Tags validieren

Das im nächsten Beispiel verwendete PDF-Dokument enthält folgende XFA-Daten (Ausschnitt):

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
      ...
      <x:xmpmeta xmlns:x="adobe:ns:meta/"
                 x:xmptk="Adobe XMP Core 4.2.1-c041 52.337767, 2008/04/13-15:41:00"
      >
        <config xmlns="http://www.xfa.org/schema/xci/2.6/">
          ...
          <log xmlns="http://www.xfa.org/schema/xci/2.6/">
            <to>memory</to>
            <mode>overwrite</mode>
          </log>
          ...
        </config>
        <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
          ...
          <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" >
            <xmp:MetadataDate>2009-12-03T17:50:52Z</xmp:MetadataDate>
          </rdf:Description>
          ...
        </rdf:RDF>
        ...
      </x:xmpmeta>
    </xdp:xdp>

Der Wert eines bestimmten XML-Knotens kann mit dem Tag `<withNode />` getestet werden:

    <testcase name="hasXFAData_WithNode">
      <assertThat testDocument="xfa/xfa-enabled.pdf">
        <hasXFAData>
          <withNode tag="xmp:MetadataDate"
                    value="2009-12-03T17:50:52Z"
                    defaultNamespace="http://www.xfa.org/schema/xci/2.6/" />
        </hasXFAData>
      </assertThat>
    </testcase>

| PDFUnit analysiert die XFA-Daten des aktuellen PDF-Dokumentes und ermittelt die Namensräume selbständig, lediglich der Default-Namespace muss angegeben werden.

Sollte der XPath-Ausdruck für den Knoten zu mehreren Treffern führen, wird der erste Treffer verwendet.

Zur Umsetzung ergänzt PDFUnit intern vor dem Knoten den Pfad-Bestandteil `"//"`. Aus diesem Grund darf der Knoten im Test kein Pfad sein, der die Wurzel `"/"` enthält.

Prüfungen auf Attribut-Knoten sind selbstverständlich auch möglich:

    <testcase name="hasXFAData_WithNode_NamespaceDD">
      <assertThat testDocument="xfa/xfa-enabled.pdf">
        <hasXFAData>
          <withNode tag="dd:dataDescription/@dd:name"
                    value="movie"
          />
        </hasXFAData>
      </assertThat>
    </testcase>

### XPath-basierte XFA-Tests

XPath kann mehr, als nur einzelne Knoten zu benennen. Mit dem Tag `<matchingXPath />` können alle Möglichkeiten von XPath genutzt werden.

Die nächsten beiden Beispiele zeigen, was machbar ist:

    <testcase name="hasXFAData_FunctionStartsWith">
      <assertThat testDocument="xfa/xfa-enabled.pdf">
        <hasXFAData>
          <!-- complete value: 'movie' -->
          <matchingXPath expr="starts-with(//dd:dataDescription/@dd:name, 'mov')" />
        </hasXFAData>
      </assertThat>
    </testcase>

    <testcase name="hasXFAData_MatchingXPath_FunctionCount_MultipleInvocation">
      <assertThat testDocument="xfa/xfa-movie.pdf">
        <hasXFAData>
          <matchingXPath expr="//pdf:Producer[. ='Adobe LiveCycle Designer ES 8.2']" />
          <matchingXPath expr="count(//processing-instruction()) = 30" />
        </hasXFAData>
      </assertThat>
    </testcase>

Eine kleine Einschränkung muss genannt werden. Die XPath-Ausdrücke können nur mit den Möglichkeiten ausgewertet werden, die die verwendete XPath-Implementierung bietet. PDFUnit nutzt normalerweise die JAXP-Implementierung des verwendeten JDK. Damit ist die XPath-Kompatibilität aber vom JDK/JRE abhängig und unterliegt dem Wandel der Zeit.

### Default-Namensraum in XPath

XML-Namensräume werden automatisch ermittelt, aber der verwendete Default-Namensraum muss explizit angegeben werden. Weil der XML-Standard mehrere, verschiedene Deklarationen in einem Dokument zulässt, ist nicht automatisch klar, welcher Default-Namensraum benutzt werden soll, wenn tatsächlich mehrere Deklarationen verwendet werden. Deshalb muss er im Test angegeben werden:

    <testcase name="hasXFAData_DefaultNamespace_matchingXPath">
      <assertThat testDocument="xfa/xfa-movie.pdf">
        <hasXFAData>
          <matchingXPath expr="count(//default:subform[@name ='movie']//default:field) = 5"
                         defaultNamespace="http://www.xfa.org/schema/xfa-template/2.6/"
          />
        </hasXFAData>
      </assertThat>
    </testcase>

Aus dem gleichen Grund muss der Default-Namensraum auch bei der Verwendung des Tags `<withNode />` mitgegeben werden:

    <!--
      The default namespace has to be declared,
      but any alias can be used for it.
    -->
    <testcase name="hasXFAData_DefaultNamespace_WithNode_AnyAlias">
      <assertThat testDocument="xfa/xfa-enabled.pdf">
        <hasXFAData>
          <withNode tag="foo:log/foo:to"
                    value="memory"
                    defaultNamespace="http://www.xfa.org/schema/xci/2.6/" />
        </hasXFAData>
      </assertThat>
    </testcase>

| Der Alias für den Default-Namensraum kann beliebig gewählt werden.

Zurück | Nach oben | Weiter
3.28. Version | Zum Anfang | 3.30. XMP-Daten