SOAP-Dokumentation aus WSDL anbieten

(Auszug aus "XSLT Kochbuch" von Sal Mangano)

Problem

Sie verwenden SOAP und WSDL, um eine kommerzielle, dienstleistungsbasierte Sitearchitektur aufzubauen. Dabei möchten Sie, dass Entwickler zu den verfügbaren Diensten vollständige und passende Informationen bekommen können.

Lösung

Die Lösung erstellt einen WSDL-basierten Server für die Dokumentation von Diensten: also einen Dienst, der Information über Dienste bietet, sozusagen ein Metadienst. In diesem Beispiel wird ein Perl-basiertes CGI-Programm verwendet, das die XSLT-Verarbeitung einer einzigen WSDL-Datei anstößt, in der Angaben über alle in der Firma verfügbaren Dienste enthalten sind. Das CGI-Programm ruft den XSLT-Prozessor mit einem system-Aufruf auf. Diese plumpe Art ist ausreichend für einen Prototyp, aber nicht für den Einsatz in der Produktion. Eine bessere Lösung würde die Perl-Module XML::LibXML und XML::LibXSLT verwenden. Und eine noch bessere Architektur würde eine ausgefeiltere, serverseitige, XSLT-fähige Lösung wie Cocoon benutzen. Wir verfolgen hier einen einfachen Ansatz, damit wir uns voll auf die XSLT- und WSDL-Aspekte dieses Beispiels konzentrieren können und nicht von der CGI-Architektur davon abgelenkt werden.

Die Startseite der Website wird von einem CGI-Programm generiert, das dem Benutzer die verfügbaren Dienste und Ports anzeigt. Eine weitergehende Erklärung von Diensten und Ports finden Sie im Diskussionsteil weiter unten. Dabei wird das folgende Perl-CGI-Frontend zu Saxon benutzt:

#!/usr/bin/perl
print "Content-type: text/html\n\n" ;
system "saxon StockServices.wsdl wsdlServiceList.xslt" ;

Die Transformation erstellt ein Formular mit allen verfügbaren Diensten, Ports, Bindings und Port-Typen:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" exclude-result-prefixes="wsdl soap http mime">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>Verfügbare Dienste von ACME Webservices GmbH</title>
        <xsl:comment>WSDL-Dokumentation: Erzeugt mit wsdlServiceList.xslt</xsl:comment>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="wsdl:definitions">
    <h1>Verfügbare Dienste von ACME Webservices GmbH</h1>
    <br/>
    <form name="QueryServiceForm" method="post" action="QueryService.pl">
      <table>
        <tbody>
          <tr>
            <td>Dienste</td>
            <td>
              <select name="service">
                <option value="ALL">ALLE</option>
                <xsl:apply-templates select="wsdl:service"/>
              </select>
            </td>
          </tr>
          <tr>
            <td>Ports</td>
            <td>
              <select name="port">
                <option value="ALL">ALLE</option>
                <xsl:apply-templates select="wsdl:service/wsdl:port"/>
              </select>
            </td>
          </tr>
          <tr>
            <td>Bindings</td>
            <td>
              <select name="binding">
                <option value="ALL">ALLE</option>
                <xsl:apply-templates select="wsdl:binding"/>
              </select>
            </td>
          </tr>
          <tr>
            <td>Port-Typen</td>
            <td>
              <select name="portType">
                <option value="ALL">ALLE</option>
                <xsl:apply-templates select="wsdl:portType"/>
              </select>
            </td>
          </tr>
        </tbody>
      </table>
      <br/>
      <button type="submit" name="submit">Dienste abfragen</button>
    </form>
  </xsl:template>
  <xsl:template match="wsdl:service | wsdl:port | wsdl:binding | wsdl:portType">
    <option value="{@name}"><xsl:value-of select="@name"/></option>
  </xsl:template>
</xsl:stylesheet>

Der Benutzer kann eine Kombination von Dienst, Port, Binding und Port-Typ auswählen, zu der er eine detailliertere Information erhalten möchte. Sobald diese Angaben abgeschickt werden, extrahiert ein weiteres kleines Perl-CGI-Programm die Eingabe und ruft eine weitere XSLT-Transformation auf:

#!/usr/bin/perl

use warnings;

use strict;
use CGI qw(:standard);

my $query = new CGI ;
my $service = $query->param('service');
my $port = $query->param('port');
my $binding = $query->param('binding');
my $portType = $query->param('portType');

print $query->header('text/html');

system "saxon StockServices.wsdl QueryService.xslt service=$service port=$port binding=$binding portType=$portType"

Diese Transformation extrahiert die Dienste, die mit den Auswahlkriterien des Benutzers übereinstimmen, und zeigt detaillierte Informationen zu diesen Diensten an. Der erste Teil des Stylesheets normalisiert einige Parameter, und zwar deswegen, weil eine Attribut-Referenz in einer WSDL-Datei ein Namensraum-Präfix enthalten könnte, aber das @name-Attribut des referenzierten Elements nicht. Die gleiche Überlegung gilt bei der Erstellung von Schlüsseln:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xslt [
  <!ENTITY TNSPREFIX "'acme:'">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/">
  <!-- Abfrageparameter -->
  <xsl:param name="service" select="'ALL'"/>
  <xsl:param name="port" select="'ALL'"/>
  <xsl:param name="binding" select="'ALL'"/>
  <xsl:param name="portType" select="'ALL'"/>
  <!-- Eine Technik (bzw. ein Hack), um Variablen zu leeren, wenn der entsprechende Parameter bzw. die Verkettung von &TNSPREFIX mit dem Parameter gleich ALL ist. Beispiel: number($service = 'ALL') * 99999 + 1 ergibt 1, wenn $service ungleich 'ALL' ist, aber 100000, wenn doch, und geht dann über die Länge des Strings hinaus, wodurch substring einen leeren Wert ergibt. All das hier dient der Vereinfachung von Kreuzverweisen. -->
  <xsl:variable name="serviceRef" select="substring(concat(&TNSPREFIX;,$service),number($service = 'ALL') * 99999 + 1)"/>
  <xsl:variable name="portRef" select="substring(concat(&TNSPREFIX;,$port),number($port = 'ALL') * 99999 + 1)"/>
  <xsl:variable name="bindingRef" select="substring(concat(&TNSPREFIX;,$binding),number($binding = 'ALL') * 99999 + 1)"/>
  <xsl:variable name="portTypeRef" select="substring(concat(&TNSPREFIX;,$portType),number($portType = 'ALL') * 99999 + 1)"/>
  <!-- Diese Schlüssel vereinfachen und beschleunigen die Abfragen -->
  <xsl:key name="bindings_key" match="wsdl:binding" use="concat(&TNSPREFIX;,@name)"/>
  <xsl:key name="portType_key" match="wsdl:portType" use="concat(&TNSPREFIX;,@name)"/>
  <xsl:output method="html"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>ACME Web Services, Inc. Query Result</title>
        <xsl:comment>WSDL Documentation: Generated by wsdlServiceList.xslt</xsl:comment>
      </head>
      <body>
        <xsl:apply-templates select="wsdl:definitions"/>
      </body>
    </html>
  </xsl:template>

Hierbei vereinfachen Sie das Problem festzustellen, ob die Abfrage passende Dienste gefunden hat, dadurch, dass Sie die Resultate in einer Variablen festhalten und deren normalisierten Wert testen. Falls er leer ist, dann wissen Sie, dass die Abfrage fehlgeschlagen ist, und es wird eine entsprechende Meldung angezeigt. Diese Abfrage ist ein wenig verzwickt, weil der portType des Dienstes nur durch zwei Sprünge vom Dienst zu seinem Binding und von dort zum Port-Typ des Bindings bestimmt werden kann:

  <xsl:template match="wsdl:definitions">
    <xsl:variable name="result">
      <!-- Abfrage von Diensten, die zu den Abfrageparametern passen. Die portType-Übereinstimmung ist der einzig komplizierte Teil. Wir müssen vom Dienst-Port zum Binding und dann zum Binding-Typ traversieren, um eine Übereinstimmung zu erzielen. Deswegen die verschachtelten Aufrufe von key( ).-->
      <xsl:apply-templates select="wsdl:service[(not($serviceRef)  or @name = $service) and (not($portRef) or wsdl:port/@name = $port) and (not($bindingRef) or wsdl:port/@binding = $bindingRef) and (not($portTypeRef) or key('portType_key',key('bindings_key',wsdl:port/@binding)/@type)/@name = $portType)]"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="normalize-space($result)">
        <xsl:copy-of select="$result"/>
      </xsl:when>
      <xsl:otherwise>
        <p><b>No Matching Services Found</b></p>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

Der Rest des Stylesheets besteht überwiegend aus Anweisungen, die das WSDL in Form von HTML-Tabelleneinträgen darstellen. Zu einem Dienst kann es mehr als einen Port geben, d.h., Sie sollten noch einmal überprüfen, dass Sie Ports auswählen, die auf den abgefragten Parametern basieren:

  <xsl:template match="wsdl:service" mode="display">
    <h1><xsl:value-of select="@name"/></h1>
    <p><xsl:value-of select="wsdl:documentation"/></p>
    <table border="1" cellpadding="5" cellspacing="0"  width="600">
      <tbody>
        <xsl:apply-templates select="wsdl:port[(not($portRef) or @name = $port) and (not($bindingRef) or @binding = $bindingRef)]" mode="display"/>
      </tbody>
    </table>
  </xsl:template>

Verwenden Sie diese Schlüssel (machen Sie eine Join-Operation), um eine Verbindung zwischen Port und Binding bzw. zwischen Binding und Port-Typ herzustellen:

  <xsl:template match="wsdl:port" mode="display">
    <tr>
      <td style="font-weight:bold" colspan="2" align="center">Port</td>
    </tr>
    <tr>
      <td colspan="2"><h3><xsl:value-of select="@name"/></h3></td>
    </tr>
    <tr>
      <td style="font-weight:bold" width="50">Binding</td>
      <td><xsl:value-of select="substring-after(@binding,':')"/></td>
    </tr>
    <tr>
      <td style="font-weight:bold" width="50">Address</td>
      <td><xsl:value-of select="soap:address/@location"/></td>
    </tr>
    <tr>
      <th colspan="2" align="center">Operations</th>
    </tr>
    <xsl:apply-templates select="key('bindings_key',@binding)" mode="display"/>
  </xsl:template>
  <xsl:template match="wsdl:binding" mode="display">
    <xsl:apply-templates select="key('portType_key',@type)" mode="display">
      <xsl:with-param name="operation" select="wsdl:operation/@name"/>
    </xsl:apply-templates>
  </xsl:template>
  <xsl:template match="wsdl:portType" mode="display">
    <xsl:param name="operation"/>
    <xsl:for-each select="wsdl:operation[@name = $operation]">
      <tr>
        <td colspan="2"><h3><xsl:value-of select="@name"/></h3></td>
      </tr>
      <xsl:if test="wsdl:input">
        <tr>
          <td style="font-weight:bold" width="50">Input</td>
          <td><xsl:value-of select="substring-after(wsdl:input/@message,':')"/></td>
        </tr>
        <xsl:variable name="msgName" select="substring-after(wsdl:input/@message,':')"/>
        <xsl:apply-templates select="/*/wsdl:message[@name = $msgName]" mode="display"/>
      </xsl:if>
      <xsl:if test="wsdl:output">
        <tr>
          <td style="font-weight:bold" width="50">Output</td>
          <td><xsl:value-of select="substring-after(wsdl:output/@message,':')"/></td>
        </tr>
        <xsl:variable name="msgName" select="substring-after(wsdl:output/@message,':')"/>
        <xsl:apply-templates select="/*/wsdl:message[@name = $msgName]" mode="display"/>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="wsdl:message" mode="display">
    <xsl:variable name="dataType" select="substring-after(wsdl:part[@name='body']/@element,':')"/>
    <tr>
      <td colspan="2">
        <xsl:apply-templates select="/*/wsdl:types/*/*[@name=$dataType]" mode="display">
          <xsl:with-param name="initial-newline" select="false( )"/>
        </xsl:apply-templates>
      </td>
    </tr>
  </xsl:template>

Dieser Code stellt das XSD-Schema der Nachrichten als XML innerhalb von HTML dar. Das eigentliche Schema ist wahrscheinlich das wertvollste Stück Information, das Sie anzeigen können, um die Datentypen zu dokumentieren, die mit den Ein- und Ausgabemeldungen der Dienste verbundenen sind:

  <xsl:template match="*" mode="display">
    <xsl:param name="initial-newline" select="true( )"/>
    <xsl:if test="$initial-newline">
      <xsl:call-template name="newline"/>
    </xsl:if>
    <!-- öffnendes Tag -->
    <a>&lt;</a>
    <a><xsl:value-of select="name(.)" /> </a>
    <!-- Ausgabeattribute -->
    <xsl:for-each select="@*">
      <a><xsl:text> </xsl:text><xsl:value-of select="name(.)" />  </a>
      <a>="</a>
      <xsl:value-of select="." />
      <a>"</a>
    </xsl:for-each>
    <xsl:choose>
      <xsl:when test="child::node( )">
        <!-- schließe Start-Tag -->
        <a>&gt;</a>
        <xsl:apply-templates  mode="display"/>
        <xsl:call-template name="newline"/>
        <!-- schließendes Tag -->
        <a>&lt;</a>
        <a>/<xsl:value-of select="name(.)" /></a>
      </xsl:when>
      <xsl:otherwise>
        <a>/</a>
      </xsl:otherwise>
    </xsl:choose>
    <a>&gt;</a>
  </xsl:template>
  <!-- Füge Zeilenende hinzu und rücke dann je nach Tiefe im Schema ein -->
  <xsl:template name="newline">
    <br/>
    <xsl:for-each select="ancestor::xsd:*[not(self::xsd:schema)]">
      <xsl:text>&#160;&#160;&#160;&#160;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Diskussion

Unter XML in HTML transformieren wurde ein Nachrichten-Repository erwähnt, das Metadaten über Nachrichten festhalten kann, die in einer Client-Server-Architektur ausgetauscht werden. WSDL ist ein Beispiel für eine Art von Nachrichten-Repository-Syntax für eine webdienstbasierte Architektur. Hierbei können Sie das gleiche WSDL auch dazu verwenden, Code und Dokumentation zu generieren. Dieses Beispiel konzentriert sich jedoch auf die Bereitstellung von Dokumentation.

WSDL beschreibt Webdienste hinsichtlich der Beziehungen zwischen Diensten und Ports. In WSDL-Begriffen ist ein Port ein einzelner Endpunkt, der als Kombination eines Bindings und einer Netzwerkadresse definiert ist. Ein Binding ist ein konkretes Protokoll und eine Spezifikation eines Datenformats für einen bestimmten Port-Typ. Ein Port-Typ definiert eine abstrakte Menge an Operationen, die von einem oder mehreren Endpunkten unterstützt werden. Eine Operation ist eine Aktion, die ein Dienst ausführen kann, und wird in Form einer Nachricht definiert, die ein entsprechendes Datenpaket enthält. Das Datenpaket wird normalerweise mit einem XSD-Schema beschrieben. Der folgende Code ist ein Ausschnitt eines Beispiels für ein einfaches WSDL, das eine Menge von Diensten beschreibt, die von einer Firma namens Acme Corporation angeboten werden:

<definitions name="StockServices" targetNamespace="http://acme.com/services.wsdl" xmlns:acme="http://acme.com/services.wsdl" xmlns:xsd1="http://acme.com/stockquote.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/">

WSDL benutzt XSD-Schema als Standardmethode für die Spezifikation der Datentypen von Nachrichten, die in einer Dienstarchitektur ausgetauscht werden:

  <types>
    <schema targetNamespace="http://acme.com/services.xsd" xmlns="http://www.w3.org/2000/10/XMLSchema">
      <element name="Ticker">
        <complexType>
          <all>
            <element name="tickerSymbol" type="string"/>
          </all>
        </complexType>
      </element>
      <element name="TradePrice">
        <complexType>
          <all>
            <element name="price" type="float"/>
          </all>
        </complexType>
      </element>
      <element name="CompanyName">
        <complexType>
          <all>
            <element name="company" type="string"/>
          </all>
        </complexType>
      </element>
      <element name="ServicesInfo">
        <complexType>
          <sequence>
            <element name="Services">
              <complexType>
                <sequence>
                  <element name="Service" type="string" minOccurs="0" maxOccurs="unbounded"/>
                </sequence>
              </complexType>
            </element>
            <element name="Ports">
              <complexType>
                <sequence>
                  <element name="Port" type="string" minOccurs="0" maxOccurs="unbounded"/>
                </sequence>
              </complexType>
            </element>
            <element name="Bindings">
              <complexType>
                <sequence>
                  <element name="Binding" type="string" minOccurs="0" maxOccurs="unbounded"/>
                </sequence>
              </complexType>
            </element>
            <element name="PortTypes">
              <complexType>
                <sequence>
                  <element name="Port" type="string" minOccurs="0" maxOccurs="unbounded"/>
                </sequence>
              </complexType>
            </element>
          </sequence>
        </complexType>
      </element>
      <element name="ServicesQuery">
        <complexType>
          <all>
            <element name="Service" type="string"/>
            <element name="Port" type="string"/>
            <element name="Binding" type="string"/>
            <element name="PortType" type="string"/>
          </all>
        </complexType>
      </element>
      <element name="ServicesResponse">
        <complexType>
          <sequence>
            <any/>
          </sequence>
        </complexType>
      </element>
    </schema>
  </types>

Nachrichten verbinden Namen mit Datentypen und beschreiben, was innerhalb der Dienstarchitektur kommuniziert wird:

  <message name="GetLastTradePriceInput">
    <part name="body" element="xsd1:Ticker"/>
  </message>
  <message name="GetLastTradePriceOutput">
    <part name="body" element="xsd1:TradePrice"/>
  </message>
  <message name="GetCompanyInput">
    <part name="body" element="xsd1:Ticker"/>
  </message>
  <message name="GetCompanyOutput">
    <part name="body" element="xsd1:CompanyName"/>
  </message>
  <message name="GetTickerInput">
    <part name="body" element="xsd1:CompanyName"/>
  </message>
  <message name="GetTickerOutput">
    <part name="body" element="xsd1:Ticker"/>
  </message>
  <message name="GetServicesInput"/>
  <message name="GetServicesOutput">
    <part name="body" element="xsd1:ServicesInfo"/>
  </message>
  <message name="QueryServicesInput">
    <part name="body" element="xsd1:ServicesQuery"/>
  </message>
  <message name="QueryServicesOutput">
    <part name="body" element="xsd1:ServicesRespose"/>
  </message>

Die Port-Typen geben an, welche Operationen an einem bestimmten Dienstendpunkt (Port) verfügbar sind. Dieser Abschnitt beschreibt zwei solche Port-Typen: einen für Aktienkursinformationen und einen weiteren Dienst für die Entdeckung von Diensten. In diesem Beispiel implementieren Sie diesen Entdeckungsdienst, mit dem Unterschied, dass er eigentlich von einem Programm benutzt würde, das kein Browser ist:

  <portType name="StockPortType">
    <operation name="GetLastTradePrice">
      <input message="acme:GetLastTradePriceInput"/>
      <output message="acme:GetLastTradePriceOutput"/>
    </operation>
    <operation name="GetTickerFromCompany">
      <input message="acme:GetTickerInput"/>
      <output message="acme:GetCompanyOutput"/>
    </operation>
    <operation name="GetCompanyFromTicker">
      <input message="acme:GetCompanyInput"/>
      <output message="acme:GetTickerOutput"/>
    </operation>
  </portType>
  <portType name="ServicePortType">
    <operation name="GetServices">
      <input message="acme:GetServicesInput"/>
      <output message="acme:GetServicesOutput"/>
    </operation>
    <operation name="QueryServices">
      <input message="acme:QueryServicesInput"/>
      <output message="acme:QueryServicesOutput"/>
    </operation>
  </portType>

Die Bindings koppeln Operationen an spezifische Protokolle. Hiermit deklarieren Sie, dass sich die Operationen an das SOAP-Protokoll halten:

  <binding name="StockQuoteSoapBinding" type="acme:StockPortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="GetLastTradePrice">
      <soap:operation soapAction="http://acme.com/GetLastTradePrice"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <binding name="StockTickerSoapBinding" type="acme:StockPortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="GetTickerFromCompany">
      <soap:operation soapAction="http://acme.com/GetTickerSymbol"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <binding name="StockNameSoapBinding" type="acme:StockPortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="GetCompanyFromTicker">
      <soap:operation soapAction="http://acme.com/GetCompanyName"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <binding name="ServiceListSoapBinding" type="acme:ServicePortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="GetServices">
      <soap:operation soapAction="http://acme.com/GetServices"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>

Nun werden zwei Dienste bekannt gegeben: einer für Aktienkurse und der andere für die Entdeckung von Diensten. Beachten Sie, wie die Dienste eine Menge an Ports organisieren, um die über den Dienst verfügbare Funktionalität anzugeben:

  <service name="StockInfoService">
    <documentation>Provides information about stocks.</documentation>
    <port name="StockQuotePort" binding="acme:StockQuoteSoapBinding">
      <soap:address location="http://acme.com/stockquote"/>
    </port>
    <port name="StockTickerToNamePort" binding="acme:StockTickerSoapBinding">
      <soap:address location="http://acme.com/tickertoname"/>
    </port>
    <port name="StockNameToTickerPort" binding="acme:StockNameSoapBinding">
      <soap:address location="http://acme.com/nametoticker"/>
    </port>
  </service>
  <service name="ServiceInfoService">
    <documentation>Provides information about avaialable services.</documentation>
    <port name="ServiceListPort" binding="acme:ServiceListSoapBinding">
      <soap:address location="http://acme.com/stockquote"/>
    </port>
    <port name="ServiceQueryPort" binding="acme:ServiceQuerySoapBinding">
      <soap:address location="http://acme.com/tickertoname"/>
    </port>
  </service>
</definitions>

Wenn Sie Ihren CGI-basierten Server aufrufen, erhalten Sie einen Bildschirm, in dem Sie Dienstabfragen eingeben können. Hier können Sie die Abfrageparameter einstellen, wie Sie auch in der folgenden Abbildung sehen können.

WSDL-Abfragebildschirm

Abbildung: WSDL-Abfragebildschirm.

Wenn Sie die Abfrage abschicken, erhalten Sie das in der folgenden Abbildung gezeigte Ergebnis.

WSDL-Ergebnisbildschirm

Abbildung: WSDL-Ergebnisbildschirm.

Siehe auch

Die Spezifikationen zu WSDL finden Sie unter Web Services Description Language (WSDL) 1.1. WSDL ist noch keine offizielle W3C-Empfehlung, aber sie findet immer mehr Anerkennung und Unterstützung in der Industrie. (Anmerkung der data2type-Redaktion: Web Services Description Language (WSDL) Version 2.0.) Es gibt eine offizielle Web Services Description Working Group, die an etwas arbeitet, was eines Tages eine vom W3C abgesegnete Empfehlung werden soll.

Im Rezept XSLT in Perl benutzen finden Sie weitere Möglichkeiten dafür, eine XSLT-Verarbeitung in Perl einzubetten, ohne einen separaten Prozess dafür erzeugen (forken) zu müssen.

  

zum Seitenanfang

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2006 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT Kochbuch" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O'Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de