這裡我用
Webservice Helper 來處理 WSDL 的問題,所以範例也是 Base 在
Webservice Helper 上面,在開始前請檢查是否有
php_soap 與
php_xsl 這兩個套件。
為了相容於 Research Service 的名稱空間,在輸出入的定義上需要在包一層資料類型,所以需要以下的類型定義:
StatusResponse.class.php
<?php
/**
* Return object to Status method
*/
class StatusResponse {
/** @var string */
public $StatusResult;
}
Registration.class.php
<?php
/**
* Input object to Registration method
*/
class Registration {
/** @var string */
public $registrationXml;
}
RegistrationResponse.class.php
<?php
/**
* Return object to Registration method
*/
class RegistrationResponse {
/** @var string */
public $RegistrationResult;
}
Query.class.php
<?php
/**
* Input object to Query method
*/
class Query {
/** @var string */
public $queryXml;
}
QueryResponse.class.php
<?php
/**
* Return object to Query method
*/
class QueryResponse {
/** @var string */
public $QueryResult;
}
接著是建立 Web Service 的 Method,主要定義 Registration 跟 Query 這兩個 Method 就可以了,Registration 是用在新增 Research Service 到 Research Pane 時會呼叫的 Method,主要是提供 Research Pane 所需要的 Service 資訊。
而 Query 則是真正再處理資料查詢的 Method,而 QueryResponse 中的 domain 及 QueryId 必需與 QueryXml 中所給的相同,不然 Client 端會無法辨識回傳結果。
<?php
/**
* Microsoft Office Research Service
*
*/
class MsOfficeResearch {
/**
* Entry point to test if server is alive. Will return 'ONLINE' or 'OFFLINE'
* @param void
* @return StatusResponse
*/
function Status() {
$result = new StatusResponse;
$result->StatusResult = 'ONLINE';
return $result;
}
/**
* Basic registration entry point
* @param Registration $registrationXml
* @return RegistrationResponse
*/
public function Registration($registrationXml) {
// debugDump('registrationXml: '.$request->registrationXml);
$dom = new DOMDocument();
$proUpdate = $dom->createElementNS("urn:Microsoft.Search.Registration.Response",'ProviderUpdate');
$proUpdate->appendChild( new DOMElement('Status',"SUCCESS") );
$providers = $proUpdate->appendChild( new DOMElement('Providers') );
$provider = $providers->appendChild( new DOMElement('Provider') );
$provider->appendChild( new DOMElement('Id',"{62E1D68D-E1C4-4CC5-9D0C-D4B7999C4B77}") );
$provider->appendChild( new DOMElement('Name',"Research Service") );
$provider->appendChild( new DOMElement('QueryPath',"http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']) );
$provider->appendChild( new DOMElement('RegistrationPath',"http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']) );
$provider->appendChild( new DOMElement('Type',"SOAP") );
$provider->appendChild( new DOMElement('Revision',"1") );
$services = $provider->appendChild( new DOMElement('Services') );
$service = $services->appendChild( new DOMElement('Service') );
$service->appendChild( new DOMElement('Id',"{0297CD20-047F-4256-0104-000004040001}") );
$service->appendChild( new DOMElement('Name',"Research Service Name") );
$service->appendChild( new DOMElement('Description',"Research Service Description") );
$service->appendChild( new DOMElement('Copyright',"") );
$service->appendChild( new DOMElement('Display',"On") );
$service->appendChild( new DOMElement('Category',"RESEARCH_GENERAL") );
$response = new RegistrationResponse;
$response->RegistrationResult = $dom->saveXML($proUpdate);
return $response;
}
/**
* Basic entrypoint for Query
* @param Query $queryXml
* @return QueryResponse
*/
function Query($queryXml) {
if(is_object($queryXml)){ $queryXml = $queryXml->queryXml; }
// debugDump('queryXml: '.$queryXml);
/*解析請求的 XML*/
$dom = new DOMDocument();
$dom->loadXML($queryXml);
$domain = $dom->getElementsByTagName('Query')->item(0)->getAttribute('domain');
$queryId = $dom->getElementsByTagName('QueryId')->item(0)->nodeValue;
/*建立返回的結構*/
$packet = $dom->createElementNS("urn:Microsoft.Search.Response",'ResponsePacket');
$packet->setAttribute('revision',"1");
$response = $packet->appendChild( new DOMElement('Response') );
$response->setAttribute('domain', $domain );
$response->appendChild( new DOMElement('QueryId', $queryId) );
$range = $response->appendChild( new DOMElement('Range') );
$results = $range->appendChild( new DOMElement('Results') );
$content = $results->appendChild( new DOMElement('Content',"","urn:Microsoft.Search.Response.Content") );
/*請求查詢*/
$status = "ERROR_NO_RESULTS_FOUND";
$queryText = trim( $dom->getElementsByTagName('QueryText')->item(0)->nodeValue );
if(!empty($queryText)){
// debugDump($queryText);
$line = $content->appendChild( new DOMElement('P') );
$line->nodeValue = htmlspecialchars($queryText, ENT_QUOTES);
$status = "SUCCESS";
}
$response->appendChild( new DOMElement('Status',$status) );
/*設定回傳結構*/
$response = new QueryResponse;
$response->QueryResult = $dom->saveXML($packet);
return $response;
}
}
關於資料交換的 XML 格式如下:
Registration Response XML
<ProviderUpdate xmlns='urn:Microsoft.Search.Registration.Response'>
<Status>SUCCESS</Status>
<Providers><Provider>
<Id>{88686849-2DD9-474d-9300-778E3336FA77}</Id>
<Name>EpgTools</Name>
<QueryPath>http://localhost/service.php</QueryPath>
<RegistrationPath>http://localhost/service.php</RegistrationPath>
<Type>SOAP</Type>
<Revision>1</Revision>
<Services><Service>
<Id>63d351db-d12e-448b-8541-9f794e1ec977</Id>
<Name>Research Service Name</Name>
<Data>1031/1033/4</Data>
<Description>Research Service Description</Description>
<AboutPath>helpId:553713956</AboutPath>
<Copyright>All content Copyright (c) 2003.</Copyright>
<Display>On</Display>
<Category>RESEARCH_GENERAL</Category>
<OptionsPath></OptionsPath>
<Parental>Unsupported</Parental>
</Service></Services>
</Provider></Providers>
</ProviderUpdate>
Query XML
<QueryPacket xmlns="urn:Microsoft.Search.Query" revision="1" build="(11.0.5606)">
<Query domain="{6E3B8AA1-5131-403E-AEF3-E7AFC2E88557}">
<QueryId>{5A4FD162-DB71-45BC-8721-F059D28947B3}</QueryId>
<OriginatorId>{F6FF7BE0-F39C-4ddc-A7D0-09A4C6C647A5}</OriginatorId>
<SupportedFormats>
<Format revision="1">urn:Microsoft.Search.Response.Document:Document</Format>
<Format revision="1">urn:Microsoft.Search.Response.Content:Content</Format>
<Format revision="1">urn:Microsoft.Search.Response.Form:Form</Format>
</SupportedFormats>
<Context>
<QueryText type="STRING" language="zh-tw">test</QueryText>
<LanguagePreference>zh-tw</LanguagePreference>
<Requery></Requery>
</Context>
<Range id="result"></Range>
<OfficeContext xmlns="urn:Microsoft.Search.Query.Office.Context" revision="1">
<UserPreferences>
<ParentalControl>false</ParentalControl>
</UserPreferences>
<ServiceData>EWATW</ServiceData>
<ApplicationContext>
<Name>Microsoft Office</Name>
<Version>(11.0.5606)</Version>
<SystemInformation>
<SkuLanguage>zh-tw</SkuLanguage>
<LanguagePack>zh-tw</LanguagePack>
<InterfaceLanguage>zh-tw</InterfaceLanguage>
<Location>TW</Location>
</SystemInformation>
</ApplicationContext>
<QueryLanguage>zh-tw</QueryLanguage>
<KeyboardLanguage>zh-tw</KeyboardLanguage>
</OfficeContext>
<Keywords xmlns="urn:Microsoft.Search.Query.Office.Keywords" revision="1">
<QueryText>test</QueryText>
<Keyword>
<Word>test</Word>
</Keyword>
</Keywords>
</Query>
</QueryPacket>
Query Response XML
<ResponsePacket xmlns="urn:Microsoft.Search.Response" revision="1">
<Response domain="{6e3b8aa1-5131-403e-aef3-e7afc2e88557}">
<QueryId>{5A4FD162-DB71-45BC-8721-F059D28947B3}</QueryId>
<Range><Results>
<Content xmlns="urn:Microsoft.Search.Response.Content">
<any />
</Content>
</Results></Range>
<Status>SUCCESS</Status>
</Response>
</ResponsePacket>
範例下載:
SearchService.zip
參考資料:
Serveur SOAP en PHP 5 pour "Microsoft Office Research Service"
The Definitive Hello World Custom Research Service Tutorial
Microsoft.Search.Response.Content Schema Documentation