Vorlage

Wertauflöser - Kurzfassung

Zweck: Interpretiert eine als Parameter statisch definierte Vorlage, die über XPath (1.0) die Daten des Druck-XML für den Eingabewert einbeziehen kann, und gibt das Ergebnis als Zeichenfolge zurück.

Siehe auch: XML Parsen

images/download/attachments/169634416/image-2025-3-5_7-13-53-version-1-modificationdate-1741155232747-api-v2.png


WICHTIG◄ Der Vorlage-Wertauflöser ist im Client-Kontext (Client Workflow, Client Workflows) nicht verfügbar.


Der Vorlage-Wertauflöser interpretiert eine als Parameter statisch definierte Vorlage, die über XPath (1.0) die Daten des Druck-XML des Eingabewerts einbeziehen kann, und gibt das Ergebnis als Zeichenfolge zurück:

  • Als Eingabewert eignen sich alle serialisierbaren Objekte, die einzeln oder als Liste übergeben werden können.

  • Wenn eine Liste von Objekten übergeben wird, darf diese auch unterschiedliche Objekttypen enthalten.

  • Die übergebenen Objektdaten erscheinen im printObjects-Element des intern erzeugten Druck-XML-Dokuments (siehe Beispiel unten), auf das XPath-(1.0)-Ausdrücke innerhalb der Vorlage zugreifen können.

  • Das printObjects-Element erscheint im Druck-XML als direktes Kind des Wurzelements (<core:Print>) nach den folgenden Elementen mit Informationen zur aktuellen Sitzung:

    • Das Element <base:User> zeigt den Stand des Benutzerkontos (Benutzer-Objekt für den Benutzer der Session) zum Zeitpunkt der Anmeldung.
      ►HINWEIS◄ Mit einer Gastbenutzer-Anmeldung, erscheint stattdessen ein Gastbenutzer-Element (<base:GuestUser>).

    • Das Element <base:CompanyAccount> zeigt den Stand des Firmenkontos (Firmen-Objekt für die Firma der Session) zum Zeitpunkt der Anmeldung.

    • Das Element <locale> beinhaltet den internen Schlüsselwert für die Aktuelle Sprache als Textknoten.

    • Das Element <storage> beinhaltet alle im Ausführungskontext gültigen Variablen und deren Werte als Liste von Elementen mit folgender Struktur: <entry><key>...</key><value>...</value></entry>, wobei das <key>-Element den Variablennamen als String angibt und das <value>-Element den Wert der Variablen enthält. Ein XPath-Ausdruck wie /core:Print/storage/entry[key="test"]/value liefert also den Wert einer Variablen test.
      HINWEIS◄ Im Unterschied zu den anderen Elementen ist das <storage>-Element nicht in einem Druck-XML enthalten, wenn dieses über den Ribbon-Befehl Druck-XML ansehen (s. folgendes Beispiel) interaktiv erzeugt wird. Allerdings existieren dann auch schlicht keine Variablen.

  • Der Rückgabewert ist immer vom Typ Text (string), außer falls bei der Interpretation des Ausdrucks mit den Objektdaten ein Problem auftritt, denn dann wird "kein Wert" (null) zurückgegeben. Ein echter Fehler, der z. B. mit einer Try-Catch-Aktion "behandelt" werden könnte, wird dabei allerdings nicht ausgelöst.

Beispiel für den Inhalt eines Druck-XML-Dokuments:

Für Objekte, auf die in Übersichten und Erfassungsmasken zugegriffen werden kann, bietet das Export-Ribbon den Befehl Druck-XML ansehen an, mit der eine Ausgabe wie die folgende (basierend auf der aktuellen Auswahl) erzeugt werden kann.

Die Ausgabe des benachbarten Ribbon-Befehls XML ansehen entspricht dabei weitgehend den im Element printObjects des Druck-XML-Dokuments je Objekt enthaltenen Daten.

Das folgende Beispiel zeigt den Aufbau eines Druck-XML-Dokuments mit einem Geschäftsobjekt vom Typ "Sendung" als einziges printObject:

Struktur einer Sendung
<?xml version="1.0" encoding="UTF-8"?>
<core:Print xmlns:base="SCM.BASE" ... >
<base:User ...>
...
</base:User>
<base:CompanyAccount ...>
...
</base:CompanyAccount>
<locale>de</locale>
<printObjects>
<shp:Shipment id="305" ...>
<attributes>
<shp:ShipmentNumericValue id="63"...>
<value numericValueType="GROSS_WEIGHT" value="3.2" unit="kg"/>
</shp:ShipmentNumericValue>
...
<shp:ShipmentCompanyAddress ...>
<value companyType="CNR" reference="354234653465">
<address salutation="MR" name1="Max" name2="Mustermann"
accNumber="1234567890" accMatchCode="Mustermann"
street1="Hindenburgstraße" streetNo="15"
countryCode="DE" zipcode="82343" city="Pöcking"
stateProvince="Bayern" stateCode="BY">
<attributes>
<base:AddressCommunicationInfo communicationType="EMAIL" communicationContext="Vertrieb" ...>
<communicationValue>vertrieb@lobster.de</communicationValue>
</base:AddressCommunicationInfo>
...
</attributes>
</address>
</value>
</shp:ShipmentCompanyAddress>
...
<shp:ShipmentDate ...>
<value dateType="DELIVERY_TO">
<date start="1454454000000" timeZone="Europe/Berlin"/>
</value>
</shp:ShipmentDate>
<shp:ShipmentDate ...>
<value dateType="DELIVERY_FIXED">
<date start="1455058800000" end="1455145199999" timeZone="Europe/Berlin"/>
</value>
</shp:ShipmentDate>
...
</attributes>
<lineItems>
<lineItem numberOfPackages="3" typeOfPackaging="BAG" ...>
...
</lineItem>
<lineItem numberOfPackages="1" typeOfPackaging="BOX" ...>
...
</lineItem>
  ...
</lineItems>
</shp:Shipment>
</printObjects>
</core:Print>

Beispiele für den Zugriff auf Inhalt dieses Druck-XML-Dokuments mit XPath-Ausdrücken:

Ausdruck

Rückgabewert

Beschreibung

Da sich alle Beispiele auf denselben Startpunkt (den Sendungskopf) beziehen, wird dieser hier nur einmalig ausgeschrieben. Allen nachfolgenden Beispielen verwenden die für relative Notation ausgehend vom Sendungskopf.

/core:Print/printObjects/shp:Shipment

(gesamte Sendung)

in den folgenden Beispielen relativ als '.' adressiert

./@id

305

Das ID-Feld (id) der Sendung ist ein Attribut (@ als Präfix) im Element für den Sendungskopf (<shp:Shipment>).

./attributes/shp:ShipmentCompanyAddress/value[@companyType='CNR']/@reference

354234653465

Eine Firmenreferenz (reference) wird als Attribut aus dem value-Element eines Firmen-Adressattributs (shp:ShipmentCompanyAddress) für den Firmentyp (companyType) Versender ('CNR') gelesen.

./attributes/shp:ShipmentDate/value[@dateType='DELIVERY_FIXED']/date/@start

1455058800000

Der Von-Wert (start-Attribut) aus dem date-Elements im Wert (value) eines Datumsattributs (shp:ShipmentDate) für den Datumstyp (dateType) "Liefertermin fix" ('DELIVERY_FIXED') wird als long-Wert (in UTC-Millisekunden) zurückgegeben. In der Praxis werden Datums-/Zeitangaben oft über die date()-Funktion (s. u.) als lesbarer Textwert formatiert.

./attributes/shp:ShipmentNumericValue/value[@numericValueType='GROSS_WEIGHT']/@value

3.2

Hier wird der reine Zahlenwert (value-Attribut) aus einem numerischen Attribut vom Nummerntyp (numericValueType) "Gewicht Brutto" ('GROSS_WEIGHT') gelesen.

Einbinden von XPath-Ausdrücken innerhalb der Vorlage:

XPath-Ausdrücke und die unten beschriebenen Funktionen müssen in geschweifte Klammern "{ ... }" eingeschlossen werden, da Zeichenfolgen ohne diese Kennzeichnung als Literale direkt ausgegeben werden.

Funktionsnamen muss zuätzlich ein Dollar-Zeichen "$" vorangestellt werden.

Beispiel: Vorlage zum Erstellen einer Ausgabe im HTML-Format:

Beispiel Textvorlage
Folgende Sendung wurde zugestellt:<br>
<br>
<table>
<tr><td>SendungsNr.</td><td>{/core:Print/printObjects/shp:Shipment/@id}</td></tr>
<tr><td>Geplantes Entladedatum</td><td>{$date("dd.MM.yyyy HH:mm:ss",{/core:Print/printObjects/shp:Shipment/attributes/shp:ShipmentDate/value[@dateType='DELIVERY_FIXED']/date/@start}) }</td></tr>
</table>
<br>
Positionen
<br>
<table>
{$ foreach( {/core:Print/printObjects/shp:Shipment/lineItems/lineItem} )
<tr><td>Anzahl Packstücke: {@numberOfPackages} Packstückart:{$r("typeOfPackaging",{@typeOfPackaging})}</td></tr>
}
</table>

HTML-Ausgabe mit konkreten Sendungsdaten:

HTML-Quelltext

Ansicht im Browser

Ausgabe
Folgende Sendung wurde zugestellt:<br>
<br>
<table>
<tr><td>SendungsNr.</td><td>305</td></tr>
<tr><td>Geplantes Entladedatum</td><td>04.02.2016 09:39:00</td></tr>
</table>
<br>
Positionen
<br>
<table>
<tr><td>Anzahl Packstücke: 3 Packstückart:Beutel</td></tr>
<tr><td>Anzahl Packstücke: 1 Packstückart:Schachtel</td></tr>
</table>

Folgende Sendung wurde zugestellt:
 
SendungsNr.
305
 
Geplantes Entladedatum
04.02.2016 09:39:00
 
Positionen
Anzahl Packstücke: 3 Packstückart:Beutel
 
Anzahl Packstücke: 1 Packstückart:Schachtel

Funktionen für die Verwendung im Parameter "Vorlage"

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg WICHTIG images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg

In den folgenden Beispielen wurden die dargestellten Ausdrücke zwecks übersichtlicherer Darstellung mit Zeilenumbrüchen wiedergegeben, die teilweise innerhalb einer Konfiguration so nicht vorkommen dürfen. Das Kopieren und Einfügen solcher Ausdrücke in eine konkrete Konfiguration ist daher nicht empfehlenswert, da Fehler oder unerwartete Ergebnisse auftreten können.


Funktion

Syntax / Details

Beispiele

date()

Datums-Formatierung

{$date(Datumspattern,Datumswert[;Zeitzone])}

Das Datumspattern verwendet die Syntax für die Java-Klasse SimpleDateFormat, die unter dem folgenden Link im Detail spezifiziert ist:
https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html

Patterns können insgesamt in doppelten Hochkommas ("") eingeschlossen werden. Dies ermöglicht z. B. die Verwendung von syntaxrelevanten Zeichen wie ( ) oder , innerhalb des Patterns.

Literale Sequenzen können außerdem mit einfachten Hochkommas auskommentiert werden. Buchstaben sind in Patterns als Literale sonst unzulässig, bzw. werden nach der unten aufgelisteten Zuordnung als Platzhalten für Datumskomponenten interpretiert.

Beispiel:

{$date("h'h 'mm'm'",{timestamp})} erzeugt Ausgaben wie: "7h 05m"

►WICHTIG◄ Die Notation für das Datumspattern ist nicht identisch mit Zuordnungen im Kontext anderer Datumsfunktionen. Da sich die verwendeten Kennbuchstaben und deren Bedeutung teilweise überschneiden, ist es wichtig beim Aufbau von Patterns die spezifischen Zuordnungen und Logiken exakt zu beachten.

Die nachfolgende Tabelle dient zum schnellen Nachschlagen und beschreibt nicht alle Details:

Komponente

Beschreibung

Ausgabewerte

G

Ära (vor/nach Christus)

AD, BC

yy, y oder YY, Y

Jahr

21, 2021

M, MM, MMM, MMMM
L, LL, LLL, LLLL

Monat (Ziffern oder Name)

1-12, 01-12, Jan-Dec, January-December

D, DDD

Tag des Jahres (Ziffern)

1-366 oder 001-366

d, dd

Tag des Monats (Ziffern)

1-31, 01-31

w, ww

Kalenderwoche (Ziffern)

1-53, 01-53

W

Woche des Monats (Ziffer)

1-5

u, E

Wochentag (Ziffer oder Name)

1-7, Mon-Sun, Monday-Sunday

F

Wochentag des Monats (Ziffer)

3 (etwa in: "3. Montag im Mai")

H, HH
k, kk
h, hh (a)
K, KK (a)

Stunde des Tages

0-23, 00-23
1-24, 01-24
1-12, 01-12 (AM/PM)
0-11, 00-11 (AM/PM)

m, mm

Minute der Stunde

0-59, 00-59

s, ss

Sekunde der Minute

0-59, 00-59

S, SSS

Millisekunde in der Sekunde

0-999, 000-999

z, Z, X

Zeitzone

Europe/Berlin, -0200, -02

Beispiel: Datumsattribut "DELIVERY_FIXED" in System-Standardzeitzone ausgeben:

{$date("dd.MM.yyyy HH:mm:ss (z)",{/core:Print/printObjects/shp:Shipment/attributes/shp:ShipmentDate/value[@dateType='DELIVERY_FIXED']/date/@start})}

Ergebnis: "04.02.2020 09:39:00 (Europe/Berlin)" ... wenn die System-Standardzeitzone "Europe/Berlin" ist und das Datumsattribut existiert.

►HINWEIS◄ Wird das per XPath abgefragte Datumsattribut im Druck-XML eines Sendung nicht gefunden, führt der hier verwendete Direktzugriff zu einem Fehler und der Wertauflöser gibt ingesamt kein Ergebnis zurück. Mit der with()-Funktion (s. folgendes Beispiel) kann dieser Effekt bei Bedarf elegant vermieden werden.


Beispiel: Datumsattribut "DELIVERY_FIXED"" in der gespeicherten Zeitzone ausgeben:{$with(/core:Print/printObjects/shp:Shipment/attributes/shp:ShipmentDate/value[@dateType='DELIVERY_FIXED']/date)
{$date("dd.MM.yyyy HH:mm:ss"),{@start};{@timeZone})}
}

  • Für den Zugriff auf die beiden Felder "Von" (start) und "Zeitzone" (timeZone) desselben Datumsattributs (DELIVERY_FIXED) wird die date()-Funktion hier im Kontext einer with()-Funktion (s. u.) eingesetzt, die den gemeinsamen Bezugspunkt im Druck-XML (<date>-Knoten des Datumsattributs) für beide Zugriffe definiert.

Ergebnis: "04.02.2020 07:39:00 (UTC)" ... wenn das Datum mit Zeitone 'UTC' gespeichert wurde.

►HINWEISE◄

  • Falls das Datumsattribut keine Angabe für die Zeitzone enthält, gibt der Wertauflöser insgesamt kein Ergebnis zurück. Das passiert auch, falls sich der Ausdruck auf eines der Felder "Von" (start) oder "Bis" (end) bezieht und für dieses kein Wert vorliegt. Da das mindestens bei importierten Geschäftsobjekten durchaus vorkommen kann, sollten solche Sonderfälle ggf. mit den Funktionen if() und cmp() abgefangen werden, z. B. wie am Ende des folgenden Beispiels demonstriert.

  • Für den Fall, dass das Datumsattribut insgesamt fehlt, sind hier dagegen keine besonderen Vorkehrungen nötig, da dann die with()-Funktion ins Leere greift worauf die Datumsfunktion insgesamt nicht ausgeführt wird.


Beispiel: Datumsattribut "DELIVERY_FIXED"" in der Default-Zeitzone des angemeldeten Benutzers ausgeben:

{$date("dd.MM.yyyy HH:mm:ss (z)",
{/core:Print/printObjects/shp:Shipment/attributes/shp:ShipmentDate/value[@dateType='DELIVERY_FIXED']/date/@start};{/core:Print/base:User/@defaultTimeZone}
)}

  • Im Druck-XML sind Benutzer und Firmenkonto der Anmeldung enthalten. Hier kann deshalb per XPath einfach auf das Feld "Default-Zeitzone" (defaultTimeZone) im entsprechenden Unterknoten zugegriffen werden.

Ergebnis: "03.02.2020 21:39:00 (Pacific/Honolulu)" ... wenn die Default-Zeitzone "Pacific/Honolulu" im Benutzerkonto zugeordnet ist.

►HINWEIS◄ Falls im angemeldeten Benutzerkonto keine Angabe für die Default-Zeitzone gefunden wird, gibt der Wertauflöser insgesamt kein Ergebnis zurück. Dieser Fall kann bei Bedarf allerdings mit den Funktionen if und cmp abgefangen werden. Das könnte z. B. so aussehen:

{$date("dd.MM.yyyy HH:mm:ss (z)",
{/core:Print/printObjects/shp:Shipment/attributes/shp:ShipmentDate/value[@dateType='DELIVERY_FIXED']/date/@start};{$if ({$cmp({/core:Print/base:User/@defaultTimeZone},!=,)}){then {/core:Print/base:User/@defaultTimeZone}}{else UTC}}
)}

  • Hier wird die Zeitzone UTC als Fallback zugewiesen, falls im Benutzerkonto keine Default-Zeitzone angegeben ist.

fn()
(engl.: format number)

Zahl formatieren

{$fn(Zahlenwert[Dezimalen=2[,Ganzzahlstellen=1[,Tausendertrennzeichen=false]]])}

Diese Funktion erstellt einen formatierten String aus einem verpflichtend bereitzustellenden Zahlenwert oder einem String, der als Zahlenwert interpretierbar ist.

Die folgenden Parameter können optional angegeben werden, um Details zur Formatierung zu steuern:

Parameter

Standardwert

Wirkung

Dezimalen

2

Anzahl der ausgegebenen Nachkommastellen (inkl. Rundung)

Ganzzahlstellen

1

Mindestanzahl für Ganzzahlstellen

Tausendertrennzeichen

false

Ganzzahlziffern in Dreiergruppen mit Trennzeichen gruppieren?

HINWEIS◄ Als Dezimal- und Tausendertrennzeichen werden die für die Aktuelle Sprache anwendbaren Lokalisierungen für die Sprachverwaltungseinträge lobsterui/decimalSeparator und lobsterui/thousandsSeparator herangezogen.

Beispiel: Eine Variable mtom im Datenkontext enthält eine "Zahl mit Einheit" (UnitNumber), die mit Hinweis auf die Einheit und exakt 3 Nachkommastellen ausgegeben werden soll.

{$with({//storage/entry[key='mtom']/value})
max. take-off mass [{@unit}]: {$fn({@value},3)}
}

Ergebnis: (Beispieldaten) max. take-off mass [t]: 10,423

ANMERKUNG Die Einheit kann hier ausschließlich über den "Alias" (s. Einheiten) gekennzeichnet werden, den die XML-Struktur für die UnitNumber direkt beinhaltet. Im String-Abbild einer UnitNumber wird im Unterschied dazu der "Name" (name) des zugehörigen Dynamischen Aufzählungswerts (z. B. TON) bzw. die anwendbare Lokalisierung (z. B. "Tonne") herangezogen, um die Einheit abzubilden. Im Kontext des Vorlage-Wertauflösers gibt es keinen direkten Weg, um diese Lokalisierung ausgehend vom "Alias"-String zu erhalten.


Beispiel: Es sollen alle IDs und Namen der Attribute aufgelistet werden, die zur "Adresse" (address) des angemeldeten Benutzers gehören. Die IDs sollen dabei als exakt sechsstellige Ganzzahl (ggf. mit "Vornullen") und Tausendertrennzeichen abgebildet werden.

{$foreach({/core:Print/base:User/address/attributes/*})
#{$fn({@id},0,6,true)} - {name()}}

Ergebnis: (Beispieldaten)

#016.153 - base:AddressCommunicationInfo
#016.154 - base:AddressCommunicationInfo
#010.051 - base:AddressContact
#010.052 - base:AddressContact
#011.601 - base:AddressLinkedEntity
#016.251 - base:AddressFlag

r()
(engl.: resource)

Lokalisierung

{$r(Resource Bundle,Resource Name[,prepareValue=true[,param0[,param1,[...]]]])}

Diese Funktion ermittelt den über die Kombination aus Resource Bundle und Resource Name adressierten Übersetzungstext aus der Sprachverwaltung.

Über den optionalen Parameter prepareValue (Standardwert: true) können Escape-Ersetzungen (z. B. für ZPL-Druckbefehle) ausgeschaltet werden (false).

Über die nachfolgenden optionalen Parameter (param0, param1, ...) können Werte für die entsprechenden Platzhalter ({0}, {1}, ...) in Lokalisierungstexten bereitgestellt werden.

HINWEIS◄ Anders als andere Zugriffsmethoden für die Sprachverwaltung sieht die r()-Funktion keine Definition für einen Standardwert vor, der als Rückgabewert zugewiesen würde, wenn für die gegebene Kombination von Resource Bundle und Resource Name kein Eintrag existiert.

Beispiel: Beschriften einer Datumsangabe ausgehend von der Lokalisierung für den Datumstyp

{$with ({/core:Print/printObjects/shp:Shipment/attributes/shp:ShipmentDate/value[@dateType='DISPATCH_DATE']}) {$r(de.lobster.scm.base.bto.attribute.DateType,{@dateType})}: {$date(y-MM-dd,{date/@start})}}

Ergebnis: "Versanddatum: 2020-02-19"

  • Die r()-Funktion verknüpft hier das Resource-Bundle für alle Datumstypen mit dem Feld Datumstyp (dateType) aus dem Attributwert.


Beispiel: Hervorheben eines Werts über eine als Sprachverwaltungseintrag definierte Formatierung

{$r(textModules,highlight,,{/core:Print/base:User/address/@name1})}

Ergebnis: "►Karola◄"
... wenn der (erste) Vorname für den Benutzer der Session "Karola" lautet und in der Sprachverwaltung ein Eintrag für [textModules,highlight] existiert, der den Lokalisierungstext "►{0}◄" liefert.

with()

XPath-Kontext


{$with({XPath-Ausdruck})Template-Ausdruck}

Die with()-Funktion definiert per XPath-Ausdruck ein bestimmtes Element aus dem Druck-XML als Bezugspunkt für die relative Interpretation weiterer im Template-Ausdruck enthaltener XPath-Ausdrücke.

Da der gemeinsame Teil des XPath-Pfads dann nur einmalig im eingeklammerten Kopf des Funktionsaufrufs erscheint, fällt der Template-Ausdruck insgesamt kürzer und transparenter aus. Außerdem können die relativ definierten Ausdrücke durch Kopieren und Einfügen einfacher in einen anderen with-Kontext übertragen werden.

Die relative Interpretation von XPath-Ausdrücken im Template-Ausdruck ermöglicht auch Zugriffe auf Knoten "oberhalb" der Einstiegsebene der with()-Funktion (../). Außerdem werden innerhalb des Template-Ausdrucks natürlich auch absolute Pfade zu beliebigen anderen Elementen aufgelöst.

Der Template-Ausdruck kann beliebig komplexe Ausdrücke enthalten, also auch weitere Aufrufe der with()-Funktion, die dann vorübergehend einen neuen "verschachtelten" Kontext setzen.

►HINWEIS◄ Falls der verwendete XPath-Ausdruck mehrere Rückgabewerte liefert, gilt ausschließlich der erste "Treffer" als Kontext für den Template-Ausdruck. Um stattdessen sämtliche Rückgabewerte eines XPath-Ausdrucks zu verarbeiten, sollte die foreach()-Funktion (s. unten) anstelle von with() verwendet werden.

Beispiel: Strukturierte Ausgabe der Adresse aus einem Firmenkonto

{$with ({/core:Print/printObjects/base:CompanyAccount/address})
#{@accNumber} (ID {../@id})
{@name1} {@name2} {@name3}
{@street1} {@streetNo}
{@zipcode} {@city}
{$r(de.lobster.scm.localization.Country,{@countryCode})}
}
  • Hier dient der address-Knoten des Firmenkontos als gemeinsamer Bezugspunkt, der die meisten relevanten Daten als Felder enthält.

  • Die interne ID (id) des Firmenkontos wird hier aus einem Feld in der relativ zur Adresse übergeordneten Ebene gelesen (../@id).

  • Ausgehend vom Länderkennzeichen aus der Adresse (countryCode) wird per r()-Funktion (s. o.) der lokalisierte Volltext für das "Land" beschafft.

Ergebnis: Ausgabe des Rückgabewerts des Wertauflösers in einem Popup vom Typ "Info":
images/download/attachments/169634416/image2020-2-25_10-42-54-version-1-modificationdate-1710864213762-api-v2.png


Beispiel: Ein ähnlicher Adressblock soll für ausgewählte Auftraggeber-Firmenattribute (Firmentyp AAL, CNE) einer Bestellung erzeugt werden:

{$with ({/core:Print/printObjects/ord:Order/attributes/ord:OrderCompanyAddress/value[@companyType='AAL']/company/address})
{$r(de.lobster.scm.base.company.CompanyType,{../../@companyType})}
-------------------------------------
#{@accNumber} (ID {../@id})
{@name1} {@name2} {@name3}
{@street1} {@streetNo}
{@zipcode} {@city}
{$r(de.lobster.scm.localization.Country,{@countryCode})}
}
{$with ({/core:Print/printObjects/ord:Order/attributes/ord:OrderCompanyAddress/value[@companyType='CNE']/company/address})
{$r(de.lobster.scm.base.company.CompanyType,{../../@companyType})}
-------------------------------------
#{@accNumber} (ID {../@id})
{@name1} {@name2} {@name3}
{@street1} {@streetNo}
{@zipcode} {@city}
{$r(de.lobster.scm.localization.Country,{@countryCode})}
}
  • Als Überschrift wurder hier oberhalb des Adressblocks per r()-Funktion der lokalisierte Bezeichner für den Firmentyp ergänzt. In dieser Form kann der gesamte Ausdruck kopiert und z. B. in demselbem Template-Ausdruck andere Firmentypen wiederverwendet werden. Im Beispiel werden Auftraggeber (AAL) und Empfänger (CNE) explizit verkettet. Eine Liste sämtlicher beteiligten Firmen kann mit Hilfe der foreach()-Funktion (s. Beispiel unten) noch eleganter erzeugt werden. Allerdings kann dabei die Reihenfolge der Firmentypen nicht gesteuert werden.

Ergebnis:

images/download/attachments/169634416/image2020-2-25_11-30-15-version-1-modificationdate-1710864213764-api-v2.png

foreach()

Schleife über XPath-Liste

{$foreach({XPath-Ausdruck}) Template-Ausdruck}

Der Template-Ausdruck wird zyklisch für alle Elemente ausgewertet, die der XPath-Ausdruck zurückgibt.

Für jede Iteration der Schleife gilt dabei ein anderer Rückgabewert als Kontext für die relative Interpretation von XPath-Ausdrücken, die im Template-Ausdruck enthalten sein können.

Der Template-Ausdruck kann beliebig komplexe Ausdrücke enthalten, also auch weitere Aufrufe der foreach()-Funktion, die dann vorübergehend einen neuen "verschachtelten" Schleifenkontext setzen (s. letztes Beispiel rechts).

Beispiel: In Anlehnung an die Beispiele für die with()-Funktion (s. o.) soll eine Liste aller an einer Bestellung beteiligten Firmen ausgegeben werden.

{$foreach ({/core:Print/printObjects/ord:Order/attributes/ord:OrderCompanyAddress/value/company/address})
{$r(de.lobster.scm.base.company.CompanyType,{../../@companyType})}
-------------------------------------
#{@accNumber} (ID {../@id})
{@name1} {@name2} {@name3}
{@street1} {@streetNo}
{@zipcode} {@city}
{$r(de.lobster.scm.localization.Country,{@countryCode})}
}

Ergebnis: Eine Liste von Firmenadressen wie im vorigen Beispiel, allerdings inklusive weiterer Beteiligter, sofern vorhanden.


Beispiel: Als Baustein einer HTML-Ausgabe soll eine Tabelle erzeugt werden, die auflistet in welcher Funktion (bzgl. Firmentyp) die aktuell angemeldete Firma an einer bestimmten Bestellung beteiligt ist.

<table>{$foreach ({/core:Print/printObjects/ord:Order/attributes/
ord:OrderCompanyAddress/value[company/@id=/core:Print/base:CompanyAccount/@id]})
<tr>
<td>{@companyType}</td>
<td>{$r(de.lobster.scm.base.company.CompanyType,{@companyType})}</td>
</tr>}
</table>
  • Je Tabellezeile werden zwei Spalten ausgegeben, in denen die interen Kennung neben dem lokalisierten Volltext für den Firmentyp erscheint.

Ergebnis: (mit einer anderen Bestellung als im Beispiel für die with()-Funktion)

Rückgabewert des Wertauflösers

Anzeige im Browser

<table>
<tr><td>INV</td><td>Rechnungsempfänger</td></tr>
<tr><td>AAL</td><td>Auftraggeber</td></tr>
</table>

mit CSS-Style table,td {border:1px solid black}

images/download/attachments/169634416/image2020-2-25_15-13-0-version-1-modificationdate-1710864213769-api-v2.png


Beispiel: Aus den Daten einer Bestellung soll ein Auszug aller enthaltenen Adressen gewonnen werden, der für jede Adresse ausgewählte Adressfelder als HTML-Liste wiedergibt, sofern vorhanden.

{$with({/core:Print/printObjects})
{$foreach({.//address|.//contactAddress})
<p>ADDRESS # {@id}
<ul>{$foreach({@*[starts-with(name(),'name')
or starts-with(name(),'street')
or contains('|zipcode|city|countryCode|',concat('|',name(),'|'))]})
<li>{.}</li>}
</ul></p>}
}
  • Die umgebende with()-Funktion setzt den Kontext auf den Knoten printObjects, damit die im Druck-XML enthaltenen Adressen aus dem Sitzungskontext (/core:Print/base:User und /core:Print/base:CompanyAccount) nicht in der Auswertung erscheinen.

  • Die erste foreach()-Schleife verarbeitet sämtliche address- und contactAddress-Elemente innerhalb der Bestellung und erzeugt für jede Adresse einen HTML-Abschnitt (<p>), der die interne ID der Adresse (id) benennt, bevor die Liste (<ul>) der Details beginnt.

  • Das Auslesen der Adressfelder erfolgt über eine eingeschachtelte foreach()-Schleife, die sämtliche Attribute (@*) eines durch die übergeordnete Schleife definierten address-Elements gegen einen etwas komplexen Prädikatausdruck ([...]) prüft. Dieser demonstriert unterschiedliche Techniken für die Auswahl von Inhalten anhand des jeweiligen Attributnamens. Sinngemäß wird geprüft, ob dieser mit 'name' oder 'street' beginnt oder in der Liste {zipcode, city, countryCode} enthalten ist. Effektiv betrifft diese Regel die Adressfelder name1, name2, name3, street1, street2, streetNo, countryCode, zipcode, city. Sofern eine dieser Angaben vorhanden ist, wird der Liste (<ul>) ein Eintrag <li> mit dem Attributwert ({.})hinzugefügt.

Ergebnis: (Auszug aus einer längeren Liste)

Rückgabewert des Wertauflösers

Anzeige im Browser

<p>ADDRESS # 7652<ul>
<li>Vortex Inc.</li>
<li>Tolkienring</li>
<li>25c</li>
<li>DE</li>
<li>27259</li>
<li>Varrel</li>
</ul></p>
<p>ADDRESS # 3715<ul>
<li>FLUX DPA</li>
<li>DE</li>
<li>82343</li>
<li>Pöcking</li></ul></p>
<p>ADDRESS # 3716<ul>
<li>FLUX CNE</li>
<li>DE</li>
<li>82343</li>
<li>Pöcking</li></ul></p>
<p>ADDRESS # 4952<ul>

...

images/download/attachments/169634416/image2020-2-26_11-13-10-version-1-modificationdate-1710864213772-api-v2.png

if()

Bedingung

{$if(if-Ausdruck) {then then-Ausdruck} [{elseif (elseif-Ausdruck) elseifthen-Ausdruck}] [{else else-Ausdruck}]}
ODER wahlweise die vereinfachte Syntax: {$if(if-Ausdruck)then-Ausdruck}

Der Rückgabewert des if-Ausdrucks entscheidet darüber, welche der weiteren im Funktionsaufruf enthaltene Ausdrücke ausgewertet werden, um den Rückgabewert der if()-Funktion zu bestimmen. Entscheiden ist dabei immer, ob der Rückgabewert aus dem if-Ausdruck dem Text 'true' entspricht, wobei ausnahmsweise die Groß-/Kleinschreibung nicht beachtet wird. In diesem Fall gilt die "wenn"-Bedingung als erfüllt.

Gelegentlich können entsprechende Werte direkt aus dem Druck-XML gelesen werden, weil sie - wie im ersten Beispiel rechts - Inhalte betreffen, die als Datentyp "boolean" bereits in geeigneter Form vorliegen.

Meistens beinhaltet ein if-Ausdruck dagegen ein mehr oder weniger komplexes Prüfkriterium, in dem Inhalte anderer Datentypen über die Vergleichsfunktion cmp() "digitalisiert" also in Wahrheitswerte überführt werden können. Bei Bedarf können mehrere Wahrheitswerte mit den logischen Operatoren $and(), $or() und $not() im if-Ausdruck zu beliebig komplexen Aggregaten verknüpft werden.

Ermitteln des Rückgabewerts per Fallunterscheidung (then - elseif - else):

Ist die im if-Ausdruck spezifizierte Bedingung erfüllt, dann wird geprüft, ob der Funktionsaufruf einen Ausdruck enthält, der mit dem Schlüsselwort then ("dann") eingeleitet wird. Trifft dies zu, wird der enthaltene then-Ausdruck ausgewertet, um den Rückgabewert der if()-Funktion zu ermitteln. Wird das Schlüsselwort then nicht gefunden, tritt ein Fehler auf und der Wertauflöser liefert insgesamt das Ergebnis 'kein Wert' - außer die vereinfachte Syntax (s. o.) wird verwendet, bei der der then-Ausdruck ohne den Schlüsselwert direkt auf den if-Ausdruck folgt (s. zweites Beispiel rechts).

Ist die im if-Ausdruck spezifizierte Bedigung nicht erfüllt, dann wird im Funktionsaufruf nach Ausdrücken mit dem Schlüsselwort elseif ("sonst-wenn") gesucht. Soweit vorhanden, werden diese in der Reihenfolge ihres Auftretens verarbeitet, indem zunächst geprüft wird, ob der enthaltene elseif-Ausdurck eine Rückgabe liefert, die dem Wert 'true' entspricht. Trifft dies zu, gilt die betreffende "sonst-wenn"-Bedingung als erfüllt und der zugehörige elseifthen-Ausdruck bestimmt den Rückgabewert der if()-Funktion. Ist die "sonst-wenn"-Bedingung nicht erfüllt, dann wird der ggf. nachfolgende elseif-Ausdruck ausgewertet.

Falls für keinen der mit elseif eingeleiteten Ausdrücke die "sonst-wenn"-Bedingung erfüllt ist, oder überhaupt kein solcher Ausdruck existiert, wird geprüft ob der Funktionsaufruf einen Ausdruck mit dem Schlüsselwort else ("sonst") enthält. Trifft dies zu, bestimmt der enthaltene else-Ausdruck den Rückgabewert der if()-Funktion. Anderenfalls ist der Rückgabewert eine leere Zeichenfolge.

►ANMERKUNG◄ Technisch ist es möglich, mehrere Ausdrücke im Funktionsaufruf mit dem Schlüsselwort then oder else einzuleiten. Allerdings wird dann im Verlauf der oben beschriebenen Fallunterscheidung (ander als bei elseif) immer nur der erste "Treffer" berücksichtigt.

►WICHTIG◄ Logische Verknüpfungsfunktionen innerhalb des if-Ausdrucks oder eine elseif-Ausdrucks müssen jeweils von geschweiften Klammern eingeschlossen sein, damit wirklich das betreffende Zwischenergebnis "aufgelöst" wird:

{$if({$or(true,false)})KORREKT} liefert "KORREKT", während der Ausdruck{$if($or(true,false))KORREKT} keine Ausgabe erzeugt, weil hier der vermeintliche Aufruf der or()-Funktion als Literal mit dem Wert 'true' verglichen wird, was für den if-Ausdruck 'false' ergibt.

Beispiel: Name und Wert aller in einem hier nicht näher spezifizierten Kontext gefundenen Kennzeichenattribute (s. Kennzeichentyp) sollen in Textform aufgelistet werden. Der Kennzeichenwert soll dabei durch die Zeichen 'X' (true) und 'O' (false) symbolisiert werden.

{$foreach({.//value[@flagValue and @flagType]})
{$if({@flagValue}){then X}{else O}} - {$r(de.lobster.scm.base.bto.attribute.FlagType,{@flagType})}}}

  • Der XPath-Ausdruck in der foreach()-Funktion beruht auf der Annahme, dass im ausgewerteten Kontext alle value-Elemente, die über zwei Attribute mit den Namen 'flagValue' und 'flagType' verfügen, zu einem Kennzeichenattribut gehören.

  • Unter dieser Annahme liefert ein Kennzeichenwert (flagValue) per Definition entweder "true" oder "false", so dass sich der Rückgabewert hier ausnahmsweise direkt (also ohne Auswertung über die cmp()-Funktion) als XPath-Ausdruck {@flagValue} für den if-Ausdruck eignet.

  • Der then-Ausdruck und der else-Ausdruck innerhalb der if()-Funktion enthalten jeweils nur entsprechende Kennzeichen alt Literal.

  • Abschließend wird der lokalisierte Name für den Kennzeichentyp (flagType) per r()-Funktion (s. o.) aus der Sprachverwaltung ausgegegeben.

Ergebnis: Popup zum Status von Auswahloptionen für einen Benutzer, wobei zwei von drei Kennzeichen gesetzt sind und eines nicht gesetzt (aber mit Wert 'false' vorhanden):

images/download/attachments/169634416/image2020-2-27_13-33-40-version-1-modificationdate-1710864213775-api-v2.png


Beispiel: In Anlehnung an das vorige Beispiel soll im ausgegebenen Text ein besonderer Hinweistext (z. B. "Kontaktaufnahme unerwünscht!") erscheinen, falls im Benutzerkonto keines der verfügbaren Kennzeichen gesetzt ist, die eine Zustimmung zu bestimmten Formen der Kontaktaufnahme signalisieren:

{$if({$not({$or( {.//value[@flagType='SEND_MAIL']/@flagValue},
{.//value[@flagType='SEND_NEWS']/@flagValue})})}){$r(PRIVACY_STATUS,ZERO_SPAM)}}

  • Die Kennzeichenwerte werden (flagValue) individuell und direkt als Argumente einer or()-Funktion verknüpft.

  • Das Ergebnis der Oder-Verknüpfung wird durch die not()-Funktion negiert, da im if-Ausdruck der if()-Funktion festgestellt werden soll, ob keiner der Kennzeichenwerte gesetzt ist.

  • Unter Anwendung der vereinfachten Syntax (s. oben) wird in diesem Beispiel der then-Ausdruck direkt auf die schließende Klammer nach dem if-Ausdruck, ohne das Schlüsselwort "then " und die umgebenden geschweiften Klammern. Konkret wird hier auf die Sprachverwaltung zugegeriffen, wo eine Lokalisierung für den benutzerdefinierten Bundle/Resource-Schlüssel vorliegen sollte.

►HINWEIS◄ Beim Verarbeiten des if-Ausdrucks oben führt das Fehlen eines Kennnzeichenattributs (oder des darin enthaltenen flagValue-Felds) dazu, dass im jeweiligen Argument der or()-Funktion eine leere Zeichenfolge ("") mit 'true' verglichen wird, was 'false' liefert. Ob das Kennzeichen nicht gefunden wird oder explizit 'false' gesetzt ist, macht damit keinen Unterschied. Eine derartige "Opt-In"-Logik entspricht dem konkreten Zweck einer Zustimmung zur Kontaktaufnahme vermutlich recht gut. Für eine Interpretation der Kennzeichen nach "Opt-Out"-Logik, könnte der if-Ausdruck stattdessen z. B. so umgebaut werden:

{$if({$and( {$cmp({.//value[@flagType='SEND_MAIL']/@flagValue},=,false)}, {$cmp({.//value[@flagType='SEND_NEWS']/@flagValue},=,false)})}){$r{PRIVACY_STATUS,ZERO_SPAM}}}

  • Die Prüfung per cmp()-Funktion (s. unten) stellt dabei sicher, dass der Wert 'false' explizit als Kennzeichenwert existiert.

ANMERKUNG◄ Da die vereinfachte Syntax der if()-Funktion letztlich nur eine "bedingte Ausgabe" des then-Ausdrucks bewirkt, lässt sich ein vergleichbares Ergebnis oft auch erzielen, indem man eine vergleichbare Logik im Prädikat eines XPath-Ausdrucks innerhalb einer with()-Funktion formuliert. Für eine "Opt-Out"-Prüfung im Beispiel wäre etwa auch der folgende Ansatz zielführend:

{$with({./attributes[ .//value[@flagType='SEND_MAIL' and @flagValue='false'] and .//value[@flagType='SEND_NEWS' and @flagValue='false'] ]}){$r{PRIVACY_STATUS,ZERO_SPAM}}}

Das hier als Bezugspunkt neu einbezogene attributes-Element stammt aus dem in den vorigen Varianten nicht komplett wiedergegeben Zusammenhang der Auswertung. Das zugehörige Prädiakt stellt sicher, dass unter den betreffenden Attributen beide Kennzeichentypen gefunden werden und auch explizit den Kennzeichenwert (flagValue) 'false' definieren.


Beispiel: Der Text einer Benachrichtigung soll personalisiert werden, indem Adressmerkmale ("Anrede" und "Nachname") einbezogen werden.

Hier wird unterstellt, dass der Nachname stets im Feld "Name 3" (name3) einer Adresse eingetragen ist und das im Feld "Anrede" (salutation) die Werte 'MR' und 'MS' (s. Anrede) für den Anwendungsfall relevant sind.

{$with({/core:Print/base:User/address})
Sehr geehrte{$if({$cmp({@salutation},=,MR)}){then r Herr}
{elseif ({$cmp({@salutation},=,MS)}) Frau}
{else r User}} {@name3}!
...
}
  • Die beiden geschlechtsspezifischen Ausprägungen der Anrede werden per if/elseif explizit abgeprüft und führen zur Zuweisung des Texts aus dem then-Ausdruck oder dem elseifthen-Ausdruck. Trifft keine dieser Optionen wird per else-Ausdruck die geschlechtsneutrale Ansprache als 'User' ausgegen.

►HINWEIS◄ Nach jedem der Schlüsselwörter then, else oder elseif muss ein Leerzeichen folgen, das als Teil der Syntax und nicht etwa als Bestandteil eines nachfolgenden Literals betrachtet wird. Dagegen sieht die syntax keine Leerzeichen nach der schließenden Klammer für den elseifthen-Ausdruck vor. Aus diesem Grund schließen im Beispiel {then r Herr} und {else r User} direkt an den vorherigen Text ('Sehr geehrte') an, während das Leerzeichen vor 'Frau' in {elseif (...) Frau} notwendig ist, um den angemessenen Abstand von diesem Text sicherzustellen.

Ergebnisse:

Anrede

Benachrichtigung

MR

images/download/attachments/169634416/image2020-3-11_10-11-12-version-1-modificationdate-1710864213778-api-v2.png

MS

images/download/attachments/169634416/image2020-3-11_10-9-56-version-1-modificationdate-1710864213800-api-v2.png

(kein Wert)

images/download/attachments/169634416/image2020-3-11_10-17-32-version-1-modificationdate-1710864213781-api-v2.png

cmp()

Vergleichs-Funktion

{$cmp(linkerAusdruck,Vergleichsoperator,rechter Ausdruck[,Vergleichsdatentyp])}

Die cmp()-Funktion vergleicht die Rückgabewerte bzw. Literale von linkerAusdruck und rechterAusdruck abhängig vom angegeben Vergleichsoperator und gibt die Zeichenfolge "true" zurück, wenn die dadurch definierte Bedingung erfüllt ist (sonst "false").

Vergleichsoperator

Kriterium für Rückgabe von 'wahr'

= oder ==

linkerAusruck ist gleich rechterAusdruck

<

linkerAusdruck ist kleiner als rechterAusdruck

<=

linkerAusdruck ist kleiner oder gleich rechterAusdruck

>

linkerAusdruck ist größer als rechterAusdruck

>=

linkerAusdruck ist größer oder gleich rechterAusdruck

!=

linkerAusdruck ist nicht gleich rechterAusdruck

Der optionale Parameter Vergleichsdatentyp definiert einen spezifischen Ziel-Datentyp für die Interpretation der Rückgabewerte von linkerAusdruck und rechterAusdruck bei der Prüfung der Vergleichsbedingung.

Vergleichsdatentyp

Beschreibung

zulässige Werte

s (Standardwert)

String-Vergleich

keine

i

Integer-Vergleich

  • Wertebereich: 32-bit integer (Java)
    Min.: -2147483648 (-231)
    Max.: 2147483647 (231-1)

  • Vorzeichen (+/-) vorweg (optional)

  • danach ausschließlich Ziffern (0-9)

l

Long-Vergleich

  • Wertebereich: 64-bit long (Java)
    Min.: -9223372036854775808 (-263) Max.: 9223372036854775807 (263-1)

  • Vorzeichen (+/-) vorweg (optional)

  • danach ausschließlich Ziffern (0-9)

f

Float-Vergleich

  • Wertebereich +/-3.4e38

  • Vorzeichen (+/-) vorweg (optional)

  • ggf. Ziffern (0-9) für Ganzzahlanteil

  • ggf. Dezimalpunkt

  • ggf. Ziffern (0-9) für Dezimalen

  • ggf. Zeichen "e" für Exponentialschreibweise gefolgt von mindestens einer Ziffer ggf. mitvorangestelltem Vorzeichen

d

Double-Vergleich

  • Wertebereich +/-1.7e308

  • Vorzeichen (+/-) vorweg (optional)

  • danach Ziffern (0-9) für Ganzzahlanteil

  • ggf. Dezimalpunkt gefolgt von weiteren Ziffern (0-9) für Dezimalen

  • ggf. Zeichen "e" für Exponentialschreibweise gefolgt von mindestens einer Ziffer ggf. mit vorangestelltem Vorzeichen

►HINWEISE◄

Per Standard werden die Ausdrücke als Zeichenfolgen verglichen, was beim Vergleichen von numerischen Daten ohne Angabe für den Vergleichsdatentyp nur in Sonderfällen die gewünschten Vergleichsergebnisse liefert. Für den Vergleich von Zahlenwerten ist es daher grundsätzlich empfehlenswert immer einen geeigneten Vergleichsdatentyp anzugeben, auch wenn ein Ausdruck ohne eine explizite Spezifikation in oberflächlichen Tests plausible Ergebnisse liefert.

Wenn ein numerischer Vergleichsdatentyp angegeben wird, müssen die Rückgabewerte von linkerAusdruck und rechterAusdruck mit dem Zielformat kompatibel sein, sonst läuft der Wertauflöser insgesamt auf einen FEHLER oder das Vergleichsergebnis ist nicht aussgekräftig.

Konkret bedeutet das (s. a. Beispiele rechts):

  1. Die von einem Ausdruck gelieferte Zeichenfolge darf nicht leer sein. Kann das nicht ausgeschlossen werden, muss dieser Sonderfall im Ausdruck abgefangen werden (s. Beispiele rechts).

  2. Die Zeichenfolge muss vollständig den Kriterien für "zuässige Werte" des Datentyps entsprechen. Der Text "121.50" wird in einem Integer-Vergleich nicht etwa als Wert 121 interpretiert, sondern verursacht einen FEHLER.

  3. Der Wertebereich des Datenstyps darf nicht überschritten werden.

    • Bei einem Integer- oder Long-Vergleich verursacht ein zu hoher oder zu niedriger Wert einen FEHLER.

    • Bei einem Float- oder Double-Vergleich wird ein "zu hoher Wert" durch den oberen Grenzwert und ein "zu niedriger Wert" durch den unteren Grenzwert ersetzt. Danach wird der Vergleich ohne FEHLER aber ggf. mit einem unterwarteten Ergebnis durchgeführt.

Für Datums-/Zeitangaben, die üblicherweise als Zahlenangabe (UTC-Millisekunden) vorliegen, eignet sich ein Double-Vergleich oder ein String-Vergleich, wenn die Millisekunden je Ausdruck mit Hilfe der date()-Funktion vorher geeignet formatiert werden. Abhängig vom dabei verwendeten Datumspattern ermöglicht ein String-Vergleich dabei wesentlich spezifischere Analysen als die Bewertung der relativen Terminlage am UTC-Zahlenstrahl (s. Beispiele rechts).

Vergleiche von Wahrheitswerten, z. B. aus Kennzeichenattributen, ermöglicht bei Bedarf der String-Vergleich mit den Werten "true" und "false".

►ANMERKUNG◄ Wenn Textwerte aus Ausdrücken als Wahrheitswert verglichen werden sollen, ohne dass eine einheitliche "Groß-/Kleinschreibung" sichergestellt ist, empfiehlt es sich, je Ausdruck die and()- oder or()-Funktion zu verwenden, um die ggf. uneinheitliche Schreibung zu neutralisieren.

Beispiel: Es soll festgestellt werden, ob zwei fiktive Felder (required und granted) eines Elements (permission) auf denselben Wahrheitswert verweisen. Ein Ausschnitt aus einem Druck-XML könnte so aussehen:

<permission type="00" required="TRUE" granted="true"></permission>

Ein Ausdruck wie {$cmp(@required,=,@granted)} würde für dieses Element "false" liefern, weil die Texte hier nicht identisch sind, obwohl das vermutlich nicht dem Sinn der Prüfung entspricht. Der folgende Ausdruck sieht über die unterschiedliche Schreibweise der Kennzeichen hinweg und meldet per "true" Übereinstimmung:

{$cmp({$or({@required})},=,{$or({@granted})})}

Beispiele:

Ausdruck

Ergebnis

Anmerkungen

{$cmp(XYZ,=,XYZ)}

true

identische Literale (inkl. Groß-/Kleinschreibung)

{$cmp(XYZ,=,xyz)}

false

unteschiedliche Groß-/Kleinschreibung

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg ACHTUNGimages/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg Unterschiedliche Interpretation von führenden oder anhängenden Leerzeichen in Literaten und Rückgabewerten! Beispiele:

{$cmp(A ,=, A)}

true

Fürhende/Anhängende Leerzeichen von Literalen werden für den Vergleich getrimmt.

{$cmp( ,=,)}

true

Führende/Anhängende Leerzeichen von Literalen werden für den Vergleich getrimmt.

{$cmp({./@name2},=,xyz)}

false

Annahme: name2-Feld liefert die Zeichenfolge ' xyz ' (ohne Hochkommas)

  • Führende/Anhängende Leerzeichen von Literalen werden für den Vergleich getrimmt.

  • Zwischen doppelten Hochkommas entfällt die Trimmung für Literale. Die doppelten Hochkommas selbst werden im Vergleichswert (hier: rechterAusdruck) ignoriert.

  • Für Rückgabewerte aus Ausdrücken erfolgt grundsätzlich keine Trimmung.

{$cmp({./@name2},=, xyz )}

false

{$cmp({./@name2},=," xyz ")}

true

{$cmp({./@name2},=,xyz)}

false

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg ACHTUNGimages/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg Zahlenwerte werden als Zeichenfolgen verglichen, wenn kein Vergleichsdatentyp angegeben ist:

{$cmp(10,<,2)}

true

Die Zeichenfolge "10" rangiert bei String-Sortierung vor "2"

{$cmp(10,<,2,i)}

false

Mit dem Vergleichsdatentyp "i" werden die Ganzzahlen 2 und 10 verglichen.

{$cmp(1.2,>=,1)}

true

Die Zeichenfolge "1.2" rangiert bei String-Sortierung nach "1". Dieses Ergebnis entspricht zufällig auch der Interpretation der entsprechenden Zahlwerte (s. u.).

{$cmp(1.2,>=,1),d}

true

Mit dem Vergleichsdatentyp "d" werden die Double-Werte 1.2 und 1.0 verglichen.

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg ACHTUNGimages/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg Ist der Rückgabewert eines Ausdruck nicht zulässig für den Vergleichsdatentyp (s. Spalte "zulässige Werte" links), bricht der Wertauflöser insgesamt ohne Rückgabewert ab.

{$cmp(1.2,>=,1),i}

FEHLER

1.2" wird bei Vergleichsdatentyp "i" nicht etwa als Integer-Wert 1 interpretiert.

{$cmp(4009900508384,<,4009900600000,i)}

FEHLER

EAN-Codes liegen als Zahlenwert außerhalb des Bereichs für den Vergleichsdatentyp Integer.

{$cmp(4009900508384,<,4009900600000,l)}

true

Der Vergleichsdatentyp "l" ermöglicht den Long-Vergleich derselben Daten, da dieser Datentyp einen größeren Wertebereich abdeckt.

{$cmp({./@textValue},<,4009900600000,l)}

false

Annahme: textValue liefert die Zeichenfolge "4009900601234"

FEHLER

Annahme: {./@textValue} liefert eine leere Zeichenfolge ("")

{$cmp(0{./@textValue},<,4009900600000,l)}

true

Annahme: {./@textValue} liefert eine leere Zeichenfolge ("")

Die in linkerAusdruck als Literal vorangestellte "0" sorgt hier dafür, dass der Wert "0" angenommen wird, wenn der weitere Ausdruck eine leere Zeichenfolge liefert, weil das Feld textValue nicht vorhanden oder leer ist. Enthält das Feld dagegen eine reine Ziffernfolge, hat das Voranstellen einer "0" keinen Einfluss auf die Interpretation in einem Long-Vergleich, solange sichergestellt ist, dass in dem Feld keine Vorzeichen verwendet werden. Eine Verkettung wie "0-4009900508384" oder "0+4009900508384" fürht zu einem FEHLER in einem Long-Vergleich.

{$cmp({$if({$cmp({./@textValue},=,)})
{then 20}{else {./@textValue}}},>,-273,l)}

false

Annahme: {./@textValue} liefert eine Zeichenfolge, die als negativer Long-Wert (<=-273) interpretierbar ist.

true

Annahme: {./@textValue} liefert eine Zeichenfolge, die als positiver oder negativer Long-Wert (>-273) interpretierbar leer oder ist. Im Long-Vergleich ersetzt der Text "20" eine leere Zeichenfolge.

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg ACHTUNGimages/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg Bei einem Float-Vergleich macht sich das begrenzte Auflösungsvermögen für Dezimalzahlen vereinfacht formuliert ab der achten gültigen Ziffer bemerkbar, während der Double-Vergleich bis zu 16 gültige Ziffern präzise auflöst.

{$cmp(1,=,1.00000001,f)}

true

Die Zahlenwerte in diesem float-Vergleich werden trotz einer Differenz von 10-8 nicht als unterschiedlich gewertet, da beiden Ausdrücken derselbe float-Wert zugeordnet wird.

{$cmp(1,=,1.0000001,f)}

false

Eine Differenz von 10-7 wird in einem ähnlichen float-Vergleich dagegen als Unterschied gewertet.

{$cmp(987654321.0123456,=,987654321.0123457,d)}

false

Ein Unterschied in der 16. gültigen Ziffer wird in diesem Double-Vergleich als Unterschied gewertet.

{$cmp(987654321.01234567,=,987654321.01234568,d)}

true

Ein Unterschied in der 17. gültigen Ziffer wird in diesem Double-Vergleich nicht als Unterschied gewertet.

Beispiele für die Auswertung von Datums-/Zeitangaben (in UTC-Millisekunden) mit der Vergleichsfunktion

{$cmp({./@lastModified},>,{./@created},d)}

true

Annahme: Das Element (z. B. ein Geschäftsobjekt), dessen Zeitstempel für "Erstellt" und "Zuletzt geändert" hier verglichen werden, wurde seit dem Erstellen ein weiteres Mal gespeichert (also: "geändert").

{$cmp( {$date(y-MM-dd,{./@lastModified})},=, {$date(y-MM-dd,{./@created})},s)}

true

Annahme: Die Zeitstempel für "Erstellt" und "Geändert" des ausgewerteten Elements verweisen in der Standardzeitzone des Systems auf denselben Kalendertag.

{$cmp({$date(HHmm,{./@created};UTC)},<,0730)}

true

Annahme: Der Zeitstempel für "Erstellt" verweist auf eine Uhrzeit vor 07:30 UTC (egal an welchem Datum).

and()

UND-Verknüpfung

{$and(Ausdruck[,Ausdruck[,...]])} 

Die and()-Funktion wertet alle als Argument übergebenen Ausdrücke einzeln aus und verknüpft deren Ergebnisse als logische UND-Verknüpfung (Konjunktion), d. h. nur wenn jeder einzelne Ausdruck einen Wert liefert, der "true" entspricht (ohne Beachtung der Groß-/Kleinschreibung), liefert die und()-Funktion auch den Wert "true" - sonst "false".

Beispiele: Anstelle der hier vor allem zwecks Transparenz verwendeten Literale können XPath-Ausdrücke oder andere Funktionen eingesetzt werden.

Ausdruck

Ergebnis

Anmerkungen

{$and(true,true,FALSE,true)}

false

Ein einziger "false"-Ausdruck erzwingt "false" als Rückgabewert.

{$and()}

true

Aufruf ohne Argumente liefert den Wert "true".

{$and(true,)}

false

Ein "fehlendes" Argument wird als "false" gewertet.

{$and(true,TRUE,tRue,True,truE)}

true

Groß-/Kleinschreibung wird nicht beachtet.

{$and(true,treu)}

false

Texte, der nicht "true" entspricht, gilt als "false".

or()

ODER-Verknüpfung

{$or(Ausdruck[,Ausdruck[,...]])} 

Die or()-Funktion wertet alle als Argument übergebenen Ausdrücke einzeln aus und verknüpft deren Ergebnisse als logische ODER-Verknüpfung (Disjunktion), d. h. sobald auch nur ein Ausdruck einen Wert liefert, der "true" entspricht (ohne Beachtung der Groß-/Kleinschreibung), liefert die or()-Funktion auch den Wert "true" - sonst "false".

Beispiele: Anstelle der hier vor allem zwecks Transparenz verwendeten Literale können XPath-Ausdrücke oder andere Funktionen eingesetzt werden.

Ausdruck

Ergebnis

Anmerkungen

{$or(false,false,TRUE,false)}

true

Ein einziger "true"-Ausdruck erzwingt "true" als Rückgabewert.

{$or()}

true

Aufruf ohne Argumente liefert den Wert "true".

{$or(true,)}

true

Ein "fehlendes" Argument wird als "false" gewertet, hat aber keinen Effekt.

{$or(true,false,TRUE,false,fAlsE)}

true

Groß-/Kleinschreibung wird nicht beachtet.

{$or(false,treu)}

false

Texte, der nicht "true" entspricht, gilt als "false".

not()

Negation

{$not(Ausdruck)}

Die not()-Funktion dient zur logischen Negation eines durch den Ausdruck definierten Wahrheitswerts. Entspricht dieser der Zeichenfolge "true" (ohne Beachtung der Groß-/Kleinschreibung), lautet der Rückgabewert "false" - sonst "true".

Beispiele: Anstelle der hier vor allem zwecks Transparenz verwendeten Literale können XPath-Ausdrücke oder andere Funktionen eingesetzt werden.

Ausdruck

Ergebnis

Anmerkungen

{$not(tRuE)}

false

Ohne Beachtung der Groß-Kleinschreibung wird "true" auf "false" abgebildet und umgekehrt.

{$not(FALSE)}

true

{$not()}

FEHLER

Im Unterschied anderen logischen Funktionen führt ein Aufruf ohne Argument zu einem Fehler.

{$not(me)}

true

Jeder Text, der nicht "true" entspricht, gilt als "false" und damit den Rückgabewert "true".

{$not({./@name4})}

true

Liefert ein Ausdruck keinen Rückgabewert (leerer String), weil der adressierte Pfad nicht existiert oder keinen Text zurückgibt, lautet der Rückgabewert aus demselben Grund "true". Allerdings würde im Beispiel auch ein Feldwert von name4, der nicht "true" entspricht, "true" als Ergebnis liefern.

substr()

Teilzeichenfolge

{$substr(Startindex,Zeichenanzahl,Ausdruck)} 

Die substr()-Funktion extrahiert einen bestimmten Abschnitt aus der Zeichenfolge, im Parameter Ausdruck der als Literal oder über einen XPath-Ausdruck definiert wird. Der Funktionsaufruf verlangt zwei integer-Argumente, die die Startposition und die (maximale) Länge des Ausschnitts fest. Diese können nicht durch Ausdrücke bestimmt sein, sondern verlangen explizite Zahlenwerte (vom Typ integer):

  • Der Startindex verweist auf die Position des Zeichens, mit dem der Ausschnitt beginnen soll. Zulässig sind integer-Werte ab 0 bis zur Länge der Zeichenfolge aus dem Ausdruck. Da das ersten Zeichen im Ausdruck den Index 0 verwendet, verweist ein Startindex, der der Länge von Ausdruck entspricht, auf die Position nach dem letzten Zeichen, so dass der Rückgabewert eine leere Zeichenfolge ist. Ein Startindex außerhalb dieses Wertebereichs verursacht einen FEHLER, durch den Wertauflöser insgesamt ohne Rückgabewert beendet wird.

  • Die Zeichenanzahl gibt an wie viele Zeichen ab dem Startindex maximal aus der durch den Ausdruck definierten Zeichenfolge extrahiert werden sollen. Der Rückgabewert endet dabei spätestens mit dem letzten Zeichen aus dem Ausdruck. Zulässig sind daher beliebige positive integer-Werte sowie der Wert 0, der grundsätzlich eine leere Zeichenfolge als Rückgabewert ergibt. Ein negativer Wert für die Zeichenanzahl verursacht einen FEHLER, durch den Wertauflöser insgesamt ohne Rückgabewert beendet wird.

►HINWEIS◄ Da intern ein "Endindex" durch eine Addition von Startindex + Zeichenanzahl berechnet wird, muss diese Summe ebenfalls noch im Wertebereich für integer-Werte (max. 231-1 = 2147483647) liegen.

Beispiele: Für die folgenden Beispielen wird als Kontext ein address-Element angenommen, das im Druck-XML (Auszug) etwa so aussehen könnte:

... <address id=... name1="♥ Karola" name2="" name3="Mustermann"> ... </address> ...

Es wird angenommen, dass die Beispiel Ausdrücke in einem with()-Kontext ausgeführt werden, der auf dieses <address>-Element verweist.

Ausdruck

Rückgabewert

Anmerkungen

{$substr(2,1,{@name1})}

"K"

Die Initiale des Vornamens im Feld name1 befindet sichausnahmsweise an der dritten Position (mit Startindex 2) der Zeichenfolge, da dem eigentlichen Namen ein Symbol (♥) mit einem nachfolgendem Leerzeichen vorangestellt wurde.

{$if({$cmp({$substr(1,1,{@name1})},=," ")})
{then {$substr(2,999,{@name1})}}
{else {@name1}}
}

"Karola"

Damit ein informelles Präfix wie das ♥-Symbol im Beispiel nicht in einem Adressfeld erscheint, sorgt in diesem Ausdruck die Fallunterscheidung dafür, dass die substr()-Funktion das Präfix "abschneidet", falls ein weiterer Aufruf der substr()-Funktion an der zweiten Position des Vornamens ein Leerzeichen vorfindet.

►ANMERKUNG◄ Wegen der automatischen Trimmung von Literalen in Argumenten ist es wichtig, das Leerzeichen innerhalb der cmp()-Funktion durch doppelte Hochkommas zu kennzeichnen.

{$substr(0,1,{@name2})}

""

Der Versuch, aus dem hier nicht mit einem Wert belegten Feld name2 eine Initiale zu gewinnen, liefert eine leere Zeichenfolge.

Nun soll in einer Schleife über alle drei Namesfelder jeweils der Anfangsbuchstabe als Initiale gezogen werden, um diese zu einem persönlichen Kürzel zu verketten. Dabei soll die bereits vorgestellte Fallunterscheidung zum Abtrennen vorangestellter Symbole für jedes Feld angewendet werden.

{$foreach({@*[starts-with(name(),'name')]})
{$if({$cmp({$substr(1,1,{.})},=," ")})
{then {$substr(2,1,{.})}}
{else {$substr(0,1,{.})}}}
}

FEHLER

Dieser Ausdruck verursacht einen Fehler, wenn eines der Namensfelder leer ist (hier: name2), da dann beim rot hervorgehobenen substr()-Aufruf der Startindex 1 die Länge der Zeichenfolge (0) überschreitet. Das nächste Beispiel zeigt, wie dieses Problem umgangen werden kann.

{$foreach({@*[starts-with(name(),'name')]})
{$if({$cmp({$substr(1,1,{.}#)},=," ")})
{then {$substr(2,1,{.})}}
{else {$substr(0,1,{.})}}}
}

"KM"

Dieser Ausdruck liefert die erwartete Verkettung der Intialen aus allen verwendeten Namenskomponenten. Im Unterschied zum vorigen Beispiel wurde im kritischen substr()-Aufruf ein beliebiges Zeichen (hier: #) an den Ausdruck angehängt, der den Feldwert liefert. Anstelle einer leeren Zeichenfolge wird dann die Zeichenfolge "#" ausgewertet, als deren zweite Position immer eine leere Zeichenfolge ("") zurückgegeben wird, was nicht identisch mit dem gesuchten Leerzeichen (" ") ist.

bsh()

bsh-Skript

{$bsh(Skript-Ausdruck)} 

Der Skript-Ausdruck wird als bsh-Skript ausgeführt und der interpretierte Wert als String zurückgeliefert.

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg ACHTUNGimages/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg

Die Verwendung von Bean Shell-Skript in Lobster Data Platform / Orchestration erfordert fortgeschrittene Programmiererfahrung und intensive Systemkenntnisse.

Durch fehlerhafte Verwendung von Skript kann erheblicher und unwiderruflicher Schaden am System und dem Datenbestand entstehen.

Die Funktion bsh() dient ausschließlich zur Behandlung von Anforderungen, die so speziell sind, dass sie mit generischen Konfigurationsmöglichkeiten nicht abgedeckt werden können.

Bitte kontaktieren Sie für weitere Informationen oder bei Interesse an Schulungen/Workshops den Lobster Data Platform / Orchestration-Support per support.pro@lobster.de.