Home
Über mich
Blog
Veröffentlichungen
IT-Trainings
Impressum


Einbindung externer XML-Dokumente

Ein Teil der dargestellten Logik importiert Daten aus einem separaten XML Dokument. Das kann sehr sinnvoll sein, um zusätzliche (Standard-) Informationen in den Konvertierungsprozeß einzubinden, die im eigentlichen XML Input Dokument nicht vorhanden sind. Bevor wir uns näher ansehen, wie der Datenimport funktioniert, schauen wir uns die externen Daten an.

<Listen 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="../xsd/Listen.xsd">
 <Liste Listnr="1" Label="Flensburger Punkte">
  <Wert Key="2">3</Wert>
  <Wert Key="5">15</Wert>
  <Wert Key="15">450</Wert>
  <Default>0</Default>
 </Liste>
</Listen>

Sinnvollerweise gibt es für ein solches Standard-Dokument ein XML Schema, das eine klare Datenstruktur erzwingt, so daß die darauf aufbauende Konvertierungslogik unverändert bleiben kann.

<xs:schema 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  elementFormDefault="qualified" 
  attributeFormDefault="unqualified">
 <xs:element name="Listen">
  <xs:complexType>
   <xs:sequence maxOccurs="unbounded">
    <xs:element name="Liste">
     <xs:complexType>
      <xs:sequence>
       <xs:sequence maxOccurs="unbounded">
        <xs:element name="Wert">
         <xs:complexType>
          <xs:simpleContent>
           <xs:extension base="xs:string">
            <xs:attribute name="Key" 
             type="xs:string" use="required"/>
           </xs:extension>
          </xs:simpleContent>
         </xs:complexType>
        </xs:element>
       </xs:sequence>
       <xs:choice>
        <xs:element name="Default" type="xs:string"/>
        <xs:element name="Error" type="xs:string"/>
       </xs:choice>
      </xs:sequence>
      <xs:attribute name="Label" type="xs:string" 
        use="optional"/>
      <xs:attribute name="Listnr" type="xs:integer" 
        use="required"/>
      <xs:attribute name="Listgruppe" type="xs:string" 
        use="optional"/>
     </xs:complexType>
    </xs:element>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Über die document-Funktion wird das externe XML Dokument in eine Variable "vlisten" eingelesen. Diese Variable wird im Template "listimport" angesprochen, wobei noch zwei Parameter "plistnr" und "pkey" erwartet werden.

Nehmen Sie sich die Zeit, das folgende XPath-Statement eingehend zu studieren, denn es erklärt sehr viel über die interne Funktionsweise von XPath. Da hinter der Variable "vlisten", die hier als Variable über "$vlisten" abgesprochen werden muß, das gesamte externe Input-Dokument steht, kann über den Pfad des Root-Elements "Listen" und dessen Child-Elemente "Liste" eine komplexe Elementliste angesprochen werden. Um das richtige "Liste"-Element herauszufinden, wird dessen Attribut "Listnr" über @-Zeichen angesprochen und mit dem übergebenen Parameter "plistnr" (als Parameter mit $ ansprechbar) gleichgesetzt.

$vlisten/Listen/Liste[@Listnr = $plistnr]/Wert[@Key = $pkey]

Das Spiel wiederholt sich. In der gefundenen Liste kann es mehrere Childelemente "Wert" geben, wir suchen jenen, dessen "Key"-Attribut mit einem Parameter "pkey" übereinstimmt.

Übergibt man dem Template "listimport" also die Parameter plistnr= "1" und pKey="15", so sucht das Template im eingebundenen externen XML Dokument in der Liste mit @Listnr="1" jenen Wert, dessen Key "15" ist, findet als Ergebnis "450" und schreibt dieses Ergebnis in den Output-Stream.

Die restliche Logik dieses Templates "listimport" zielt darauf ab, zu prüfen, ob der betreffende Wert überhaupt vorhanden ist. Falls nicht, wird hier jener Wert ausgelesen, der im betreffenden "Default"-Element zugewiesen ist.

 <xsl:variable name="vlisten"
  select="document('file:///C:/wg/Listen.xml')" />
 <xsl:template name="listimport">
  <xsl:param name="plistnr" />
  <xsl:param name="pkey" />
  <xsl:choose>
   <xsl:when
    test="$vlisten/Listen/Liste[@Listnr = $plistnr]/Wert[@Key = $pkey]">
    <xsl:value-of
     select="$vlisten/Listen/Liste[@Listnr = $plistnr]/Wert[@Key = $pkey]" />
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of
     select="$vlisten/Listen/Liste[@Listnr 
      = $plistnr]/Default" />
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

Ausgehend von allen Elementen Mensch (in der xsl-for-each-Schleife angesprochen über den XPath-Ausdruck /Orte/Ort/Mensch), wurde nach dem Gehalt absteigend sortiert, Werte wie Gehalt und die Summe Kauf/Gesamt wurden dezimal-formatiert undnumeriert. Zusätzlich können gebräuchliche Techniken wie Cascading Stylesheets (<link href="print.css" rel="stylesheet" type="text/css"/>) sowie javascript zum Einsatz kommen.

In einer zusätzlichen Anweisung <tr onclick="alert('{vorname} {name} wohnt in {../name}');"/> kann definiert werden, dass eine MessageBox vom Browser aufgerufen wird, sobald Sie auf eine Zeile der Tabelle klicken. Weil die Ausgabe in einem HTML-Attribut erfolgen muss, kann der Inhalt der Datenquelle über die geschweiften Klammern {XPath-Ausdruck} eingebunden werden.

Die Dezimalformatierung erreichen Sie etwa über <xsl:value-of select="format-number(Gehalt, '#.##0,00', 'european')"/>; das setzt freilich die Top-Level-Deklaration des Dezimalformats voraus: <xsl:decimal-format name="european" decimal-separator="," grouping-separator="."/> Innerhalb der for-each-Schleife absteigend sortieren können Sie über (<xsl:sort select="Gehalt" data-type="number" order="descending"/>).

qrpic/XSL_XML2HTML2.jpg

wg / 9. Oktober 2017




Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf (info10@wilfried-grupe.de).



Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

Mobil: 0151. 750 360 61 * eMail: info10@wilfried-grupe.de