Dieses Beispiel zeigt, wie man eine oder mehrere komplexe XML-Datei erstellen kann. Die Daten liefert ein Spreadsheet, das z.B. aus einem Datastore kommen kann. 


Eine einzelne XML-Datei erstellen


Der wichtigste Step zum Erstellen einer XML-Datei ist der TextHTMLWriter.


Nehmen wir folgenden, sehr einfachen Beispiel-Flow an: 




Nehmen wir an der SearchDatastore liefert folgende Produktdaten, die in die XML Datei geschrieben werden sollen:


Die Ziel-XML Datei soll folgenden Aufbau haben: 


<?xml version="1.0" encoding="UTF-8"?>
<products>
  <product id="1">
    <name><![CDATA[K-Star - Super Shoe XI]]></name>
    <brandname><![CDATA[K-Star]]></brandname>
    <description><![CDATA[Description of Super Shoe XI]]></description>
    <price>129.99</price>
  </product>
  <product id="2">
    <name><![CDATA[Product 2]]></name>
    <brandname><![CDATA[...]]></brandname>
    <description><![CDATA[...]]></description>
    <price><![CDATA[...]]></price>
  </product>  

<products>


Hinweis: Die CDATA-Blöcke sind nicht unbedingt notwendig, vermeiden aber häufige Fehler, wenn lange Beschreibungstexte ebenfalls XML- oder HTML Tags enthalten. Man ist quasi auf der sicheren Seite, wenn man CDATA bei Textfeldern verwendet.


Öffnen Sie die Konfiguration des TextHTMLWriter Steps:


Klicken Sie auf das Plus-Zeichen, um ein Beispiel-Skript einzufügen, welches die Grundlage für die XML-Datei darstellt:


Wählen Sie den Eintrag, des Spreadsheets, welches Ihre Daten enthält und wo die Beschreibung mit "Example freemarker script..." beginnt.


Daraufhin sollte das Textfeld mit einem Beispiel-Skript gefüllt sein, was ungefähr so aussieht:



Dieses Skript gibt jede Zeile inkl. aller Spalten des Spreadsheets aus. Das ist die Grundlage zur Erstellung der XML. 

Der nächste Schritt ist, dieses Skript so anzupassen, dass die gewünschte XML-Struktur dabei heraus kommt. Dabei können Sie alle Platzhalter aus dem obigen Skript verwenden (z.B. ${row.get("name")!}] um die Spalte "name" auszugeben).



Hier noch mal das finale Skript als Text:

<?xml version="1.0" encoding="UTF-8"?>
<products>
<#list spreadsheet@SearchMasterDatastore_1.getRows() as row> 
  <product id="${row.get("identifier")!}">
    <name><![CDATA[${row.get("name")!}]]></name>
    <brandname><![CDATA[${row.get("brandname")!}]]></brandname>
    <description><![CDATA[${row.get("description")!}]]></description>
    <price>${row.get("price")!}</price>
  </product>
</#list>
<products>


Zu Erklärung:

Die wichtigste Zeile ist Zeile 3 (<#list spreadsheet@SearchMasterDatastore_1.getRows() as row>) und das dazugehörige schließende Tag </#list>.

Diese Anweisung für den dazwischenliegenden Skript-Block (alles ab <product ... bis </product>) für jede Zeile des Eingabe Spreadsheets aus. 


Wichtig: 

Bitte kopieren Sie dieses Skript nicht blind heraus. Die Variable spreadsheet@SearchMasterDatastore_1 wird in Ihrem Flow mit Sicherheit eine andere Bezeichnung haben. Es würde nicht funktionieren, wenn Sie das hier einfach kopieren). Befolgen Sie den Weg, wie hier beschrieben. 


Wenn Sie sich jetzt die Vorschau anzeigen lassen, sollte die gewünschte XML-Struktur mit allen Produkten des Input-Spreadsheets auftauchen. 



Alternative:

Es gibt noch eine Alternative, um eine sehr sehr simple XML-Datei mit dem Step Spreadsheet2XML zu erstellen. Allerdings hat man in diesem Step sehr wenig Einfluss auf Struktur und Aussehen der XML-Datei (z.B. wäre es nicht möglich das Attribut "id" im <product> Tag zu realisieren.)



Mehrere XML-Dateien erstellen

Um mehrere XML-Dateien gleichzeitig zu erstellen z.B. "Eine Datei pro Bestellung" kann der Step TextHTMLWriterMultiOutput verwendet werden. 


Tauschen Sie dazu den Step TextHTMLWriter aus und ersetzen Ihn durch den TextHTMLWriterMultiOutput.


Um eine Datei pro Produkt zu erzeugen, muss das vorherige Skript umgestellt werden:


<#list spreadsheet@SearchMasterDatastore_1.getRows() as row> 

  <#assign xmlfilecontent>
    <?xml version="1.0" encoding="UTF-8"?>
    <products>

      <product id="${row.get("identifier")!}">
        <name><![CDATA[${row.get("name")!}]]></name>
        <brandname><![CDATA[${row.get("brandname")!}]]></brandname>
        <description><![CDATA[${row.get("description")!}]]></description>
        <price>${row.get("price")!}</price>
      </product>
    <products>
  </#assign>

  <#assign xmlfilename = "product"+row.get("identifier") + ".xml" />
  ${output(xmlfilecontent, xmlfilename, "UTF-8")}
  
</#list>


  • die vollständige XML-Struktur wandert ins innere der <#list> Schleife
  • mit <#assign xmlfilecontent> wird die XML-Struktur in eine Variable mit dem Namen "xmlfilecontent" geschrieben
  • mit <#assign xmlfilename = "product"+${row.get("identifier")!} + ".xml" /> wird der Dateiname nach dem Muster product1.xml, product2.xml usw. erzeugt (die Zahl ist z.B. die Artikelnummer aus der Spalte identifier)
  • mit dem Befehl ${output(xmlfilecontent, xmlfilename, "UTF-8")} wird letztendlich der Inhalt der Variable xmlfilecontent in die Datei xmlfilename geschrieben und als Encoding wird UTF-8 verwendet.



XML-Tags dynamisch aus Spalten des Spreadsheets erzeugen

In den obigen Beispielen werden die Spaltennamen hartkodiert angegeben. Das ist passend, wenn man genau weiss, welche Spalten man im Spreadsheet hat und in der XML-Datei haben will.

Möchte man hingegen aber die XML-Datei dynamisch aus allen vorhandenen Spalten erzeugen, dann bietet sich folgendes Beispiel-Skript an. 


<?xml version="1.0" encoding="UTF-8"?>

<#list spreadsheet@SearchMasterDatastore_1.getRows() as row> 
  <#list row.getCols() as col>
        <${col.getTitle()!}><![CDATA[${col.get()!}]]></${col.getTitle()!}>
  </#list>
</#list>


Hier ist der Gedanke, dass man zwei geschachtelte Schleifen hat. Die erste iteriert über die Zeilen (rows) und die zweite über jede Spalte der Zeile (col). 

Die Tag-Namen werden dann über col.getTitle() zusammengebaut. Über col.get() erhält man den Wert der Spalte / Zelle. 


Die innere Schleife kann man z.B. noch mit WENN-DANN Bedingungen anreichern, um nur bestimmte Spaltennamen zuzulassen oder nur Spalten, die mit einem Prefix beginnen (starts_with() Funktion).