Transformieren von Nachrichten mit Mule DataWeave – Teil 2: Bedingungen und reguläre Ausdrücke

Keine Kommentare

Nach der Einführung sollten die Grundlagen von DataWeave schon halbwegs bekannt sein. Heute geht es darum, wie man dynamisch steuern kann, was in den Zieldaten steht – quasi um das „if“ von DataWeave. Die Steuerungsdaten für die Bedingungen können dabei aus dem Inhalt der Nachricht oder Metadaten stammen.

Als Beispiel nutze ich für diesen Teil eine einfache JSON-Struktur mit einer Liste von Personen:

{
   "persons": [
   {
       "gender": "male",
       "name": "Peter"
   },
   { 
       "gender": "female",
       "name": "Paula"
   }
 ]
}

Neben dem Namen hat jede Person noch ein gender-Attribut. Im ersten Schritt wandeln wir die Struktur 1:1 in XML um:

%dw 1.0
%output application/xml encoding="utf-8"
--- 
personen: {
  (payload.persons map {
      person: {
        geschlecht: $.gender,
        vorname: $.name
      }
    }
  )
}

Als XML erhalten wir dann:

<?xml version='1.0' encoding='UTF-8'?>
<personen>
   <person>
     <geschlecht>male</geschlecht>
     <vorname>Peter</vorname>
   </person>
</personen>

Bisher ganz einfach. Was eigentlich schon im ersten Teil dieser Serie stehen sollte, ist das Attribut für das Encoding (encoding=“utf-8″). Ohne nutzt Mule das Standard-Encoding des Betriebssystems (z. B. „windows-1252“), was erstens nicht unbedingt gewünscht ist und zweitens zu unterschiedlichen Encodings in den Stages vom Entwicklerrechner bis in die Produktion führen kann.

Im nächsten Schritt filtern wir das Ergebnis, so dass in der Ausgabe nur die Männer übrig bleiben. Dazu wird das DataWeave-Skript um einen Filter ergänzt:

%dw 1.0
%output application/xml encoding="utf-8"
--- 
personen: {
  (payload.persons filter ($.gender == "male") map {
      person: {
        geschlecht: $.gender,
        vorname: $.name
      }
    }
  )
}

Jetzt wird Paula unterschlagen und nur noch Peter bleibt im Ergebnis stehen:

<?xml version='1.0' encoding='UTF-8'?>
<personen>
  <person>
    <geschlecht>male</geschlecht>
    <vorname>Peter</vorname>
  </person>
</personen>

Ein Filter reicht nicht mehr aus, wenn alle Elemente im Ergebnis auftauchen sollen, aber – abhängig von einer Bedingung – in unterschiedlicher Form. Nehmen wir also an, dass statt des XML-Tags <person> die Spezifikation jetzt <mann> und <frau> fordert. Wären sie in zwei getrennten Listen, ginge das noch mit dem Filter, gemischt in einer gemeinsamen Liste jedoch nicht mehr. Mit Bedingungen lässt sich auch dies lösen:

%dw 1.0
%output application/xml encoding="utf-8"
--- 
personen: {
 (payload.persons map {
      (mann: {
        vorname: $.name
      }) when ($.gender == "male"),
      (frau: {
        vorname: $.name
      }) when ($.gender == "female")
    }
  )
}

Möchte man – wie hier gezeigt – komplette Attribut-Wert-Paare ausschließen, muss man um das ganze Paar noch runde Klammern setzen. Tauscht man dagegen nur Werte aus, kann man darauf verzichten. In dem letzten Fall lässt sich mit dem Schlüsselwort „otherwise“ auch das Äquivalent eines else-Zweiges implementieren.

Für Freunde der Verneinung steht statt „when“ auch noch „unless“ zur Verfügung. Logische Verknüpfungen erfolgen nicht mit den Java-/JavaScript-typischen Zeichen && bzw. ||, sondern über die Schlüsselwörter „and“ bzw. „or“. Für Verneinungen gibt es noch „not“.

Wer mit Texten arbeitet, erwartet sicher auch reguläre Ausdrücke. Diese kommen in DataWeave in drei Varianten vor. Die einfachste ist in Bedingungen. So passt die Bedingung

($.gender matches /.*male/)

sowohl auf „male“ als auch auf „female“ (und alle anderen Strings, die auf „male“ enden).

Das Schlüsselwort „replace“ erlaubt das Suchen und Ersetzen mit regulären Ausdrücken. Der Ausdruck

replace /(\d+)/ with "ID"

tauscht alle Zahlen durch die Zeichenkette „ID“ aus.

Wendet man den Operator „match“ mit einem regulären Ausdruck auf einen String an, steht im Ergebnis ein Array. Unter dem Index 0 findet sich der gesamte Match wieder, ab Index 1 die Teilausdrücke des gesamten Ausdrucks. Dazu ein Beispiel:

%dw 1.0
%output application/xml encoding="utf-8"
--- 
personen: {
  (payload.persons map {
      person: {
        vorname: $.name,
        vorwahl: ($.phone match /(\d+)\/(\d+)/)[1],
        nummer: ($.phone match /(\d+)\/(\d+)/)[2]
      }
    }
 )
}

Was passiert hier? Aus dem Attribut „phone“ (bitte in der Beispieleingabe am Anfang des Artikels dazudenken) fischt sich der reguläre Ausdruck die Teile vor und hinter einem Schrägstrich getrennt heraus. Mit dem angehängten [0] und [1] landen sie dann in den Tags <vorwahl> und <nummer> im XML.

So, das soll für heute reichen. Im nächsten Teil werde ich mich dann mit Gruppierungsfunktionen beschäftigen.

Links

Roger Butenuth

Dr. Roger Butenuth hat in Karlsruhe Informatik studiert und anschließend in Paderborn promoviert (Kommunikation in Parallelrechnern). Er hat langjährige Erfahrung in der Projekt- und Produktentwicklung.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.