Kataloge für den Mittelstand

Für den elektronischen Handel ist ein digitaler Katalog unersetzlich. In Deutschland soll sich mit BMEcat-XML ein Standardformat dafür etablieren. Perl-Module helfen bei dessen Erzeugung und Verwaltung.

In Pocket speichern vorlesen Druckansicht 2 Kommentare lesen
Lesezeit: 12 Min.
Von
  • Frank-Peter Reich
Inhaltsverzeichnis

Zumindest beim Handel zwischen Geschäftsleuten, modern B2B (‘Business to Business’) genannt, etablieren sich elektronische Verfahren. Sie ermöglichen es, den Einkauf zu vereinfachen und zu beschleunigen. Eine Voraussetzung dafür ist ein digitaler Katalog, den Anbieter ihren Kunden zur Verfügung stellen, so dass diese ihn in ihr Beschaffungswesen (‘Procurement’) integrieren können. Hier zu Lande verlangen immer mehr Einkäufer, diese Daten im Format BMEcat-XML zu bekommen.

Auf Initiative des Bundesverbands Materialwirtschaft, Einkauf und Logistik e. V. (BME) und unter Beteiligung namhafter deutscher Unternehmen haben das Fraunhofer Institut für Arbeitswirtschaft und Organisation sowie die Universitäten Essen und Linz diesen Standard zur elektronischen Datenübertragung für Artikelkataloge entwickelt (siehe www.bmecat.org/bmecat). Version 1.0 liegt seit November 1999 vor und seitdem erfährt das Format eine rasante Verbreitung. Die Gründe liegen nicht nur in der Unterstützung durch namhafte Industrieunternehmen:

  • BMEcat schließt eine Lücke, denn allein im Internet existieren über 160 verschiedene Katalogsprachen.
  • Die Edifact-Nachrichtentypen PRICAT und PRODAT, die zur Katalogübertragung in Frage kommen würden, fanden wie Edifact selbst keine flächendeckende Verbreitung.
  • Das Format verwendet den Internet-Standard XML, die Extensible Markup Language. Sie ermöglicht es, in einem Katalogdokument Struktur und Daten gleichzeitig zu kodieren.
  • Alle führenden Shop-Systeme (besonders des Beschaffungsbereiches) können BMEcat importieren.
  • Der Lieferant muss nur wenige Restriktionen einhalten, sodass BMEcat flexibel nutzbar ist, bis hin zu nutzereigenen Erweiterungen.
  • Für die Übertragung der Kataloge stehen drei Modi zur Verfügung: Gesamter Katalog, Produkt- und Preisaktualisierung.
  • In die BMEcat-Spezifikation sind viel Aufwand, Erfahrung und wissenschaftliche Gründlichkeit eingeflossen. Sie deckt die Anforderungen an einen digitalen Katalog nahezu vollständig ab.

Ein BMEcat-Dokument besteht aus zwei Hauptelementen:

  • Kopf: Informationen zum Katalog selbst, dem Lieferanten und dem Käufer. Die Käuferdaten kommen ins Spiel, weil BMEcat von festen Beziehungen zwischen Ein- und Verkäufern ausgeht. Das Element ‘Agreement’ kann Informationen zum zugrunde liegenden Rahmenvertrag enthalten.
  • Transaktion: legt fest, ob es sich um einen völlig neuen Katalog oder die Aktualisierung von Produkt- beziehungsweise Preisdaten handelt.

Innerhalb der Transaktion finden sich unter anderen die Detailinformationen für den Katalog:

  • Merkmalssystem: eindeutige Liste von Merkmalsgruppen mit festen Eigenschaften einer Artikelgruppe (zum Beispiel Schrauben: Verwendungszweck, Oberfläche, Länge, Durchmesser, Kopfform).
  • Struktur: der vom Händler benutzte Katalogaufbau; jeder Katalog ist als Baumstruktur darstellbar und alle seine Informationen können darin abgebildet werden.
  • Artikeldaten: Artikel-, Order- und Preisedetails, mediale Informationen, Merkmale und Referenzen auf andere Artikel (Ersatzteil).
  • Artikelzuordnung: Positionierung der Artikel in die Blätter des Katalogbaumes.
Mehr Infos

Um die Definition von Merkmalsystemen kümmern sich neutrale Instanzen (zum Beispiel ecl@ss vom Institut der deutschen Wirtschaft), sie richtet sich ausschließlich nach normierten Artikeleigenschaften. Artikelmerkmale können zwar auch Strukturen definieren, sind jedoch nicht mit der Katalogstruktur zu verwechseln. Diese ist im Allgemeinen der Katalogaufbau des Herstellers beziehungsweise Lieferanten. Dessen Einteilung des Kataloges in Gruppen und Untergruppen ist im Allgemeinen historisch gewachsen. Zumeist richtet sie sich nach Merkmalen, zum Beispiel Befestigungstechnik / Schrauben / Verwendungszweck / Oberfläche. Die Wahl der Bezeichnungen für die gleiche Eigenschaft kann firmenspezifisch variieren. So subsumiert ein Hersteller ‘Alu’, ‘Messing’, ‘Bronze’, ‘Edelstahl’ unter ‘Oberfläche’, der zweite unter ‘Farbe’ und der dritte unter ‘Material’. Oder die Produkte bekommen andere Namen, etwa ‘Klinke’ statt ‘Türdrücker’.

Bezüglich der Katalogstruktur gelten im BMEcat folgende Regeln:

  • Der Baum besteht aus der Wurzel (root), internen Knoten (nodes) und Blättern (leaves, singular leaf).
  • Die Tiefe der Hierarchie ist beliebig.
  • Zweige können unterschiedlich tief sein, das heißt, die Baumstruktur muss nicht balanciert sein.
  • Jeder Knoten hat eine ID, die Wurzel ID ist 0.
  • Jeder Knoten kennt nur seine Eltern (über die PARENT_ID), jedoch nicht seine Kinder.
  • Allen Knoten können Informationen (Texte, Bilder beziehungsweise andere Medien) zugewiesen werden.
  • Artikel dürfen nur in den Blättern existieren.
  • Verweise auf einen Artikel können in mehreren Blättern stehen.
  • Jeder Artikel ist eindeutig im Katalog.

In den Artikeldetails können zusätzlich verschiedene Warengruppen angegeben werden, sodass bezüglich der Datenstrukturierung keine Anforderungen unberücksichtigt bleiben.

Aufbau und Pflege eines multimedialen digitalen Kataloges stellen eine nicht zu unterschätzende Herausforderung dar, die nur mit geeigneter Software und ausreichend warenfachkundigem Personal zu beherrschen ist. Wie aus einem beliebigen Format, etwa aus der Warenwirtschaft exportierten Dateien, eine BMEcat-Datei entsteht, beschreibt der folgende Text.

Ziele bei der Erstellung des Konvertierungsmoduls in Perl waren:

  • Zwecks Wiederverwendung soll ein Modul alle BMEcat-spezifischen Programmteile zusammenfassen.
  • Ein- und Ausgabe sind in getrennten Schritten vorzunehmen, um leichter verschiedene Importformate unterstützen zu können und später weitere Operationen auf den eingelesenen Daten zu ermöglichen.
  • Eine grafische Benutzerschnittstelle soll die Benutzerakzeptanz erhöhen und die Auswahl der Ein- und Ausgabedateien erleichtern.

Zur Konvertierung der Daten in BMEcat-XML ist es sinnvoll, die Daten intern in geeigneten Strukturen zu halten - zumal in Hinblick auf das zweite Design-Ziel. Durch Verschachtelungen der Perl-eigenen Datentypen ist es möglich, Strukturen auf Basis der Klassendiagramme aus der BMEcat-Dokumentation im Speicher zu erzeugen. Das Element Artikel mit einigen ‘ARTICLE_DETAILS’ sieht etwa folgendermaßen aus:

$ART_SYS->{"52389"}->{'ARTICLE_DETAILS'} =
[
[ 'DESCRIPTION_SHORT' => $DESCRIPTION_SHORT ],
[ 'DESCRIPTION_LONG' => $DESCRIPTION_LONG ],
[ 'EAN' => $EAN ]
];

$ART_SYS ist die Hash-Referenz auf das Artikelsystem. Mit dem Schlüssel ‘52389’ ist darin die Hash-Referenz auf alle Angaben zum betreffenden Artikel abgelegt. Unter dem Schlüssel ‘ARTICLE_DETAILS’ enthält diese eine Referenz auf eine Liste von Referenzen von Key-Value-Datenpaaren. Zwar wäre auch eine Implementierung mit Hashes denkbar, dies würde jedoch beim Herausschreiben einen größeren Aufwand erfordern, da die BMEcat-DTD alle Elemente in einer bestimmten Reihenfolge erwartet. Die ist durch die Array-Struktur leichter zu erzeugen.

Alle Werte können auch einzeln gesetzt werden, zum Beispiel die Planlieferzeit, der 10. Wert der Artikeldetails:

@{$ART_SYS->{"52389"}-> {'ARTICLE_DETAILS'}}[9] = \
['DELIVERY_TIME' => $DELIVERY_TIME];

Hier derefenziert der Cast-Operator @{} die Liste mit dem Schlüssel ‘ARTICLE_DETAILS’. Hashes finden Verwendung, wenn es um den Zugriff über Schlüssel geht. Da dies beliebige Zeichenketten sein können, sind sowohl generische Nummernsysteme als auch eher exotische Werksartikelnummern verwendbar. Die Benutzung der Elementbezeichnungen von BMEcat-XML ermöglicht eine stärkere Abstraktion der Ausgabemethoden.

Listen sichern die Einhaltung der Reihenfolge. Zudem kann man an sie mit push() leicht einen Wert anhängen. Dies wird unter anderem angewendet, um einem Knoten der Katalogstruktur eine unbestimmte Anzahl von Bildern oder Beschreibungen oder einem Artikel mehrere Preise zuzuweisen. Zur Beschreibung von Bildern benutzt BMEcat die üblichen MIME-Typen. Die ausschließliche Nutzung von Referenzen, auch innerhalb der innersten Liste, verbessert die Performance bei großen Datenmengen.

Vermutlich kann trefflich darüber gestritten werden, ob das benutzte Verfahren zur Anlage erweiterter Datenstrukturen leicht zu handhaben oder eher gewöhnungsbedürftig ist. Auf jeden Fall ist es fehlerträchtig: Das versehentliche Anlegen neuer Schlüssel in Hashes kann der Interpreter nicht verhindern, selbst das strict-Pragma leistet das nicht. Für das Verbergen interner Strukturen hinter einer objektorientierten Schnittstelle sprechen weiterhin bessere Plausibilitätsprüfungen und die Erleichterung späterer Strukturänderungen sowie die Tatsache, dass Perls objektorientierte Eigenheiten auf Referenzen beruhen und somit der Implementierung sehr entgegenkommen.

Listing 1 (MiniKatalog.pl) gibt anhand des kleinsten möglichen Kataloges mit nur einem Artikel einen Überblick über die Möglichkeiten des BMEcat-Moduls, das auf XML::Generator.pm basiert (vgl. http://www.fischerwerke.de/fixings/katalog/9_Hohlraumbef.pdf).

Mehr Infos

Listing 1

#!/usr/local/bin/perl
use XML::BMEcat;
use File::Basename;
my $BMEcat = XML::BMEcat->new();
$BMEcat->setOutfile("MiniKatalog.xml");
my $Header = $BMEcat->creatHeader();
$Header->setTransaction('T_NEW_CATALOG', [ 'prev_version' => '1.0' ]);
my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
$Header->setGeneralInfo(
'GENERATOR_INFO' => "created by " . basename($0),
'LANGUAGE' => 'DEU',
'CATALOG_ID' => 6,
'CATALOG_VERSION' => 100,
'CATALOG_NAME' => "fischer BEFESTIGUNGSSYSTEME",
'DATE' => sprintf ("%4d-%02d-%02d",1900+$year,++$mon,$mday),
'TIME' => sprintf ("%02d:%02d:%02d",$hour,$min,$sec),
'CURRENCY' => 'DEM',
'MIME_ROOT' => "/images"
);
$Header->setBuyerInfo(
'BUYER_ID' => "0815",
'BUYER_NAME' => 'FOO',
...
);
$Header->setAgreementInfo(
...
);
$Header->setSupplierInfo(
'SUPPLIER_ID' => "1",
'SUPPLIER_NAME' => "fischerwerke",
...
);
$Header->setConfigInfo(
'FEATURE_SYSTEM_NAME' => 'Internal',
'VERBOSE' => 0,
'CHAR_SET' => 'ISO-8859-1',
'DTD' => 'bmecat_new_catalog.dtd'
);
$BMEcat->writeHeader();
### Merkmalssystem ###
my $FeatureSystem = $BMEcat->creatFeatureSystem();
$FeatureSystem->addFeatureGroup(
'116',
'Länge' => "mm",
'min. Dicke bis zu ersten Trägerschichten' => "mm",
'Typ' => ""
);
$BMEcat->writeFeatureSystem();
### Katalogstruktur ###
$Header->setConfigInfo('GROUP_SYSTEM_ID' => '01-1-00/01');
my $GroupSystem = $BMEcat->creatGroupSystem();
my $CatalogGroup =
$GroupSystem->creatCatalogGroup('02');
$CatalogGroup->setData(
'PARENT' => 0,
'NAME' => "fischer Befestigungskatalog",
'SORT' => 5
);
$CatalogGroup =
$GroupSystem->creatCatalogGroup('04');
$CatalogGroup->setData(
'PARENT' => 2,
'NAME' => "Allgemeine Befestigungen",
'SORT' => 5
);
$CatalogGroup =
$GroupSystem->creatCatalogGroup('06');
$CatalogGroup->setData(
'PARENT' => 2,
'NAME' => "Hohlraumbefestigungen",
'SORT' => 10
);
$CatalogGroup =
$GroupSystem->creatCatalogGroup('08');
$CatalogGroup->setData(
'PARENT' => 4,
'NAME' => "fischer Gipskartondübel GK",
'SORT' => 5,
'LEAF' => 1
);
$CatalogGroup->addDescription("inkl. 1 Setzwerkzeug");
$CatalogGroup->addMime('image/jpg',
"fis101274.jpg", "normal");
...
$BMEcat->writeGroupSystem();
### Artikel ###
my $ArticleSystem =
$BMEcat->creatArticleSystem();
my $Article =
$ArticleSystem->creatArticle('52389');
$Article->setMainInfo(
'mode' => 'new',
'SUPPLIER_AID' => '52389'
);
$Article->setFeatureGroup('116');
$Article->setFeatureValues(
'22',
'25',
'GK'
);
$Article->addMime('image/jpg',
'4006209523896.jpg', 'normal');

$DESCRIPTION_LONG = <<'--end--';
Der fischer Gipskartondübel GK ...
...
--end--
$Article->setDetails(
'DESCRIPTION_SHORT' =>
'Der Schnellmontagedübel für Gipskarton',
'DESCRIPTION_LONG' => $DESCRIPTION_LONG,
'EAN' => '4006209523896'
);
$Article->setOrderDetails(
'ORDER_UNIT' => "Pkg.",
'CONTENT_UNIT' => "Stk.",
'NO_CU_PER_OU' => 100
);
$Article->setPriceDetails(
'valid_start_date' => '1999-10-01',
'valid_end_date' => '2000-09-31'
);

$Article->addPrice(
'price_type' => 'net_list',
'PRICE_AMOUNT' => '50,00',
'PRICE_CURRENCY' => 'EUR'
);
$BMEcat->writeArticleSystem();
### Artikel-Gruppenzuweisung ###
$Article->map2Group("08");
$BMEcat->writeArticleGroupMap();
### Schluss ###

$BMEcat->writeTail();

Der erste Schritt beim Erstellen eines Katalogs ist immer die Instanziierung eines Objekts der Klasse BMEcat. Es übernimmt die Verantwortung für die von ihm aggregierten Objekte der Klassen Header, FeatureSystem, GroupSystem und ArticleSystem.

Im Header-Objekt sind neben den schon erwähnten Informationen zum gesamten Dokument (zum Beispiel Character-Set) sowie Konfigurationsoptionen (zum Beispiel Verbose-Mode) hinterlegt. Diese Werte kann man einzeln setzen und so jederzeit korrigieren.

Ein FeatureSystem muss man nicht nur für den Fall instanziieren, dass es selbst mit zu übertragen ist, sondern immer dann, wenn die Artikel Merkmale benutzen. Der Artikel bekommt nur noch die entsprechende Merkmalsgruppe und passende Werte für die einzelnen Eigenschaften zugewiesen. Da für das Produkt im Beispiel noch keine Klassifizierung existiert, benutzt es eine generische. Dies implementiert eine Grundlage des BMEcat-Formats, die Förderung der Klassifizierung.

Es folgt das CatalogGroup-Objekt. Eine bei der Instanziierung an creatCatalogGroup() übergebene Node-ID identifiziert jedes dieser Objekte eindeutig. Stimmen die Katalog- mit den Warengruppen überein, könnte man letztere benutzen. Das dürfte jedoch eher selten zutreffen.

Im Beispiel ist die Gruppe mit der Node-ID ‘08’ die unterste der Hierarchie (Blatt), oft auch als Produktebene bezeichnet. Hier lassen sich Informationen für die gesamte Kataloggruppe unterbringen, beispielsweise eine kurze Beschreibung oder eine Schemazeichung (addDescription beziehungsweise addMime()).

Das ArticleSystem-Objekt bildet den Hauptteil des Katalogs. $Article ist die an die Klasse Article gebundene Objektreferenz. In der internen Struktur ist sie wie beschrieben als Wert zum Schlüssel ‘52389’ abgelegt. Lediglich die Erzeugung läuft jetzt schrittweise ab. Einen neuen Article instanziiert die Methode creatArticle() der Klasse ArticleSystem. Sie erzeugt mittels übergebenem Schlüssel im Hash eine Instanzvariable, die als Wert eine durch den Konstruktor der Klasse Article erzeugte Referenz erhält, und gibt sie zurück.

package ArticleSystem;
sub creatArticle {
my $self = shift;
my $key = shift;
return $self->{$key} = Article->new();
}

package Article;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
}

So erstellten Artikeln ordnen set...()-Aufrufe allgemeine Angaben zu, etwa Merkmale, MIME-Definitionen, Details, Bestell- und Preisinformationen. Hierbei ist die Reihenfolge des Aufrufs gleichgültig, das Modul sorgt für die nötige Ordnung und nimmt eine Plausibilitätsprüfung vor. Für weitere Informationen zu einzelnen Artikeln steht die Methode $Article->setDetails() zur Verfügung. Groß geschriebene Schlüssel bezeichnen XML-Elemente, klein geschriebene deren Attribute.

Abschließend weist map2Group() den Artikel seiner Produkt-Gruppe mit der ID 8 zu. Sämtliche für einen einzelnen Artikel beschriebenen Schritte sind in der Regel für alle Produkte zu erledigen. $BMEcat->writeArticleSystem() kann entweder jeden Artikel einzeln oder den ganzen Stamm auf einmal schreiben. Im ersten Fall muss man ArticleSystem jedes Mal neu instanziieren.

Ein Perl/Tk-GUI hilft bei der Eingabe von Header-Daten sowie der Wahl von Ein- und Ausgabedateien.

Für die Validierung der Ausgabedatei catalog.xml sollte ebenfalls ein Perl-Modul zur Anwendung kommen. Zumindest während der Entwicklungsphase ist diese Kontrolle nötig, um korrekte BMEcat-Kataloge zu garantieren. Da das bekannte Modul XML::Parser keine DTDs verarbeitet, kann es die Validierung nicht übernehmen. Die besten Aussichten verspricht zurzeit XML::Checker::Parser im Modul libxml-enno, jedoch befindet es sich noch im Alphastadium. An einigen Stellen im Web gibt es Möglichkeiten der Online-Validierung (www.e-pro.de), oder man greift auf andere Lösungen unter Java zurück (zum Beispiel aus IBMs Xerces-Projekt). James Clarks nsgmls aus seinem jade-Paket ist ein weiterer validierender Parser.

Perl haftet unter anderem das Vorurteil an, dass die Skripte nicht nur schwer zu lesen, sondern auch nur auf der Kommandozeile zu bedienen seien. Mit dem Tk-Modul ließ sich jedoch schnell ein hilfreiches GUI schaffen (siehe Abbildung). Die dort eingesetzten Karteikarten dienen zum Editieren der Kopfinformationen. Darin eingebettet sind scrollbare Text-Widgets, die Label und Eingabefelder enthalten. Dadurch können sehr viele Einträge auf kleinem Raum angeordnet werden.

Frank-Peter Reich
ist Unix-Systemspezialist bei dem SAP/R3-Outsourcer Nowis GmbH Oldenburg.

[1] Oliver Fischer; Perl-Know-how; Segensreich; Tipps und Tricks für OO-Programme

[2] Christian Kirsch; Perl-Know-how; Elemente mit System; XML-Parser für Perl-Scripts

[3] Christian Kirsch; Programmierung; Glänzende Perlen; Tk-Oberflächen für Perl-Scripts; iX 12/1996, S. 156

Mehr Infos

iX-TRACT

  • Mittelständische Händler, die sich im Beschaffungswesen behaupten wollen, müssen ihren Katalog vollständig digital bereitstellen können.
  • Als von der Industrie gefordertes Format verbreitet sich BMEcat-XML. Dieses Format lässt sich mit Perl aus beliebigen Eingabedaten erzeugen.
  • Zur leichteren Bedienung eignet sich eine Perl/Tk-Oberfläche für das Modul.
Mehr Infos

Lizenzdetails

BMEcat ist grundsätzlich frei verwendbar. Softwareunternehmen, die es in ihre Software einbauen wollen, sollten die BMEcat-Initiative hierüber informieren (info.bmecat@bme.de) und beachten, dass Logo und Markenzeichen geschützt sind; die Rechte liegen beim BME. Der Verband will auch in Zukunft die Kontrolle über den Standard behalten und bereitet ein Zertifizierungsverfahren für BMEcat-Software vor.

(ck)