2012-04-25 60 views
0

所以Zimbra的解析SOAP響應,我使用PHP跟一個Zimbra的SOAP服務器。回覆標籤爲<soap:Envelope>。由於名稱空間的原因,我無法解析XML響應。用SimpleXML和XPath

的XML看起來是這樣的:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> 
    <soap:Header> 
    <context xmlns="urn:zimbra"> 
     <change token="20333"/> 
    </context> 
    </soap:Header> 
    <soap:Body> 
    <CreateAccountResponse xmlns="urn:zimbraAdmin"> 
     <account id="83ebf344-dc51-47ae-9a36-3eb24281d53e" name="[email protected]"> 
     <a n="zimbraId">83ebf344-dc51-47ae-9a36-3eb24281d53e</a> 
     <a n="zimbraMailDeliveryAddress">[email protected]</a> 
     </account> 
    </CreateAccountResponse> 
    </soap:Body> 
</soap:Envelope> 

我提出一個新的SimpleXMLElement對象:

$xml = new SimpleXMLElement($data); 

谷歌上搜索了一下後,我發現我需要註冊的名稱空間。所以我這樣做:

$xml->registerXPathNamespace('soap', 'http://www.w3.org/2003/05/soap-envelope'); 

然後,我可以很容易地得到<soap:Body>標籤。

$body = $xml->xpath('//soap:Body'); 

但我不能獲取(使用XPath)後的任何元素:

$CreateAccountResponse = $xml->xpath('//soap:Body/CreateAccountResponse'); 

這將返回一個空數組。我可以遍歷XML,以獲取該元素。

$CreateAccountResponse = $body[0]->CreateAccountResponse; 

這工作得很好,但現在我想要得到的<a>標籤,特別是之一。所以,我想這一點:

$zimbraId = $CreateAccountResponse->account->xpath('a[@n=zimbraId]'); 

沒有運氣,我得到了一個空白陣列。這是怎麼回事?爲什麼我不能使用xpath獲取元素(不以soap:開頭)?

如何根據n屬性獲取<a>標籤?

P.S.我知道,idname也都在<account>標籤的屬性,但也有一幫更<a>標籤,我想用n屬性來獲得。

注:我想提高Zimbra的圖書館爲我工作的應用程序。目前的代碼來獲取<a>標籤如下:

$zimbraId = strstr($data, "<a n=\"zimbraId\""); 
$zimbraId = strstr($zimbraId, ">"); 
$zimbraId = substr($zimbraId, 1, strpos($zimbraId, "<") - 1); 

很明顯,我想刪除這個代碼(有也是一些正則表達式(不寒而慄)在稍後的代碼),並使用XML解析器。

回答

4

要檢索的元素有一個命名空間爲好,即urn:zimbraAdmin

<CreateAccountResponse xmlns="urn:zimbraAdmin"> 

xmlns屬性狀態的默認命名空間的任何子元素,所以您要實際檢索的元素有一個命名空間,即使不使用前綴(見the wikipedia article的一些例子)。如果你像爲http://www.w3.org/2003/05/soap-envelope那樣指定一個命名空間前綴,你應該沒問題。

$xml->registerXPathNamespace('soap', 'http://www.w3.org/2003/05/soap-envelope'); 
$xml->registerXPathNamespace('zimbra', 'urn:zimbraAdmin'); 
$CreateAccountResponse = $xml->xpath('//soap:Body/zimbra:CreateAccountResponse'); 
+0

酷,謝謝。那就是訣竅。一旦我註冊了'zimbra'命名空間,它就可以運行(只要我用'zimbra:'前綴)。我用這個xpath查詢得到我想要的元素:''// soap:Body/zimbra:CreateAccountResponse/zimbra:account/zimbra:a [@ n =「zimbraId」]''。 – 2012-04-25 20:57:23

+0

我也意識到如果我將它保存到一個變量中,我必須在元素上註冊'PathNamespace'。例如'$ x = $ CreateAccountResponse [0] - > account;'我必須做'$ x-> registerXPathNamespace('zimbra','urn:zimbraAdmin');'讓它工作。然後,我可以執行'$ x-> xpath('zimbra:a [@ n =「zimbraId」]')'。 – 2012-04-25 21:06:10

+1

這篇文章似乎很不幸合作:http://www.qc4blog.com/?p=443 – erikxiv 2012-04-25 21:20:35