Mini Beispiel eines XML Import

Ok. Hier das Mini Beispiel eines Datenimports aus XML in FileMaker Tabellen.

Die Materie ist etwas sperrig, weil man mit drei XML Dateien umgeht: Quell-XML [1] wird mit Transformations-XML [2] zu Ziel-XML [3] umgeformt. Da verliert man leicht den Überblick.

Es kommt das systematische Problem dazu, dass XML ein Baum ist. Genauer gesagt: Baumstrukturen darstellen kann. Ein Datensatz (heißt da Knoten oder Element) kann sich in mehrere Arten Unter-DS verzweigen, die sich wieder verzweigen koennen, usw.

Und FileMaker hat nur normale Tabellen mit einer Art Datensätzen. Um einen Baum abzubilden braucht man in FileMaker mehrere Tabellen. (Das ist etwas vereinfacht, es gibt auch Bäume innerhalb von FileMaker Tabellen bei Verwendung von Selbstbeziehungen. Damit kann man aber auch nicht die getrennten Importvorgänge vermeiden).

Man importiert jede `Sorte’ Unterdatensaetze mit einem dafuer angepassten XSLT in eine FM Tabelle.

Fangen wir vorsichtig an. Das sei unsere Datenquelle [1] data.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<daten>
    <arzneimittel>
      <Zulassungsnummer>12-23-34-45</Zulassungsnummer>
      <bezeichnung>Musterarzneimittel</bezeichnung>
      <packungen>
        <packung>
          <inhalt>50</inhalt>
          <einheit id ="110009">ML</einheit>
        </packung>
        <packung>
          <inhalt>100</inhalt>
          <einheit id="110009">ML</einheit>
        </packung>
        <packung>
          <inhalt>200</inhalt>
          <einheit id="110009">ML</einheit>
        </packung>
      </packungen>
      <indikationen>
        <indikation>
          <diagnose>Durchfall</diagnose>
          <min_dos>20</min_dos>
          <max_dos>40</max_dos>
          <einheit id="110009">ML</einheit>
        </indikation>
        <indikation>
          <diagnose>Kopfweh</diagnose>
          <min_dos>10</min_dos>
          <max_dos>20</max_dos>
          <einheit id="110009">ML</einheit>
        </indikation>
      </indikationen>
    </arzneimittel>
</daten>

Die kann FileMaker so nicht einlesen, weil FM die Grammatik FMPXMLRESULT praeferiert.

Was man sich darunter (FMPXMLRESULT) genau vorzustellen hat, macht man sich am besten klar, indem man eine beliebige FileMaker Datenbank greift und einen Export im Format XML mit der Grammatik FMPXMLRESULT vornimmt.

Das Ergebnis könnte so aussehen:

<?xml version="1.0" encoding="UTF-8" ?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
  <ERRORCODE>0</ERRORCODE>
  <PRODUCT BUILD="01-25-2023" NAME="FileMaker" VERSION="ProAdvanced 17.0v3"/>
  <DATABASE DATEFORMAT="D.m.yyyy" LAYOUT="" NAME="test.fmp17" RECORDS="2" TIMEFORMAT="k:mm:ss "/>
  <METADATA>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Feld1" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Feld2" TYPE="TEXT"/>
  </METADATA>
  <RESULTSET FOUND="2">
    <ROW MODID="0" RECORDID="1">
      <COL>
	<DATA>11</DATA>
      </COL>
      <COL>
	<DATA>12</DATA>
      </COL>
    </ROW>
    <ROW MODID="0" RECORDID="2">
      <COL>
	<DATA>21</DATA>
      </COL>
      <COL>
	<DATA>22 text</DATA>
      </COL>
    </ROW>
  </RESULTSET>
</FMPXMLRESULT>

In den Zeile <FIELD …> steht in dem Attribut NAME der Feldname des jeweiligen FileMaker Feldes.

<ROW> ist jeweils ein Datensatz und <COL> ist je ein Feld. Darunter gibt es noch <DATA>, weil es ja Wiederholfelder und Bezugsfelder gibt, die mehrere Werte pro Feld haben koennen.

`Sowas’ kann FileMaker auch einlesen. Das ist das Ziel der Transformation, das Ziel-XML [3], welches wir mit einem XSLT erzeugen wollen.

ZB. kann dieses XSLT (das Transformations-XML [2]!) die Elemente <unter-unter> als Datensätze in FileMaker einlesen:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		version="1.0">
  <!--
      hier wird ein Template (sowas wie eine Schablone) definiert,
      welches auf den Root Knoten `/' passt. Den gibt es garantiert
      nur einmal und darum laesst sich damit das aussere Geruest
      unseres Ziel XML bauen.
  -->
  <xsl:template match="/">
    <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
      <ERRORCODE>0</ERRORCODE>
      <PRODUCT BUILD="" NAME="" VERSION=""/>
      <DATABASE DATEFORMAT="M/d/yyyy" LAYOUT="" NAME="" RECORDS="1" 
		TIMEFORMAT="h:mm:ss a"/>
      <METADATA>
	<!-- Felddefinitionen fuer die FM Daten.  Unter NAME="xxx"
	     koennen die Feldnamen frei gewaehlt werden, die im FM
	     Import Dialog erscheinen. 
	     Pro weiterem Importfeld je eine Zeile neu anlegen.
	-->
	<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="inhalt" TYPE="TEXT"/>
	<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="einheit" TYPE="TEXT"/>
	<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="einheit_id" TYPE="TEXT"/>
      </METADATA>
      <RESULTSET FOUND="1">
	<xsl:apply-templates />
      </RESULTSET>
    </FMPXMLRESULT>
  </xsl:template>
 
  <!--
    Das Template fuer die FM Datensaetze. Hier muessen wir uns entscheiden, 
    welcher Knoten die einzelnen FM Datensaetze trennen soll.  Hier soll es das 
    Element &l;tunter-unter&gt; sein.
  -->
  <xsl:template match="packung">
    <ROW MODID="0" RECORDID="0">
      <!-- 
	   Wo finden sich die Daten im XML Baum?  Hinter dem
	   select-tag steht der Pfad durch den Baum. Der einfachste
	   Pfadausdruck ist ".", der Wert des Elements selber.
      -->
      <COL><DATA><xsl:value-of select="inhalt"/></DATA></COL>
      <COL><DATA><xsl:value-of select="einheit"/></DATA></COL>
      <!--
	  Mit dem "@" kann man auf Attributwerte zugreifen
      -->
      <COL><DATA><xsl:value-of select="einheit/@id"/></DATA></COL>
    </ROW>
  </xsl:template>
</xsl:stylesheet>

Hier werden drei FileMaker Felder definiert (“inhalt”, “einheit” und “einheit_id”) und denen werden die Textinhalte der Elemente <inhalt>, <einheit> und <einheit_id> der XML Datenquelle zugewiesen.

Das Ergebnis ist praktisch der Import folgender Tabelle:

inhalt/th>

einheit einheit_id
50 ML 110009
100 ML 110009
200 ML 110009

Nach diesem Schema kann man Schritt fuer Schritt (und XSLT fuer XSLT) die ganze Information aus dem XML nach FileMaker bringen.

Probiere es einfach mal aus :).

Es gibt dann noch ein paar Aspekte, die ich nicht behandelt habe. Die XML Elemente koennen zu einem Namensraum gehoeren, so wie die Elemente <xsl:template>, <xsl:value-of> und <xsl:stylesheet> zu dem Namensraum xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” gehören. Und es gibt eine ganze Wissenschaft von den Pfaden, mit denen man sich durch den XML Baum bewegt. Das traegt den Namen XPATH. Wir haben zwei ganz einfache XPATH Ausdrücke kennengelernt: “.” und “@”.

2 thoughts on “Mini Beispiel eines XML Import

  1. Joachim Voigt

    hallo Jens, diese Art des Imports mit xslt hattest du mir vor Jahren mal gebastelt, seitdem komme ich zurecht, indem ich dein Stylesheet von damals modifziere. Nun würde ich gern verstehen, wo hier das Universal Stylesheet ins Spiel kommt … kommt das denn ohne eine individuelle Zuordnung von value-of-select aus (die sich allein aus der Reihenfolge ergibt, wenn mich nicht alles täuscht)?

    Reply
    1. jens Post author

      Hallo!

      Der Unterschied ist, dass das universelle XSLT für jedes Feld (und jedes Attribut) einen extra Datensatz erzeugt. Das Ergebnis ist dann schwieriger in FileMaker zu importieren. Man bekommt viel zu viele Datensätze. Das ist der Preis für die ‘passt-immer’ Eigenschaft.

      LG Jens

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *