2011-12-15 80 views
1

我正在使用CURL向Mondrian發送SOAP請求。這是PHP代碼,其中正在使用捲曲:如何使用PHP和SimpleXML解析名稱空間的SOAP XML響應

$poststring = 
    '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-  ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
    <SOAP-ENV:Header /> 
    <SOAP-ENV:Body> 
    <Execute xmlns="urn:schemas-microsoft-com:xml-analysis"> 
    <Command> 
    <Statement> 
    select {[Measures].[Unit Sales]} on columns from Sales 
    </Statement> 
    </Command> 
    <Properties> 
    <PropertyList> 
    <Catalog>FoodMart</Catalog> 
    <DataSourceInfo>Provider=Mondrian;DataSource=MondrianFoodMart;</DataSourceInfo> 
    <Format>Multidimensional</Format> 
    <AxisFormat>TupleFormat</AxisFormat> 
    </PropertyList> 
    </Properties> 
    </Execute> 
    </SOAP-ENV:Body> 
    </SOAP-ENV:Envelope>'; 

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, 'http://localhost:8080/mondrian/xmla'); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $poststring); 
curl_setopt_array($ch, $this->_curlOptions);   
$_rawResult = curl_exec($ch); 

curl_close($ch); 

接收SOAP響應我從蒙德里安得到的是:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP- ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" > 
<SOAP-ENV:Header> 
</SOAP-ENV:Header> 
<SOAP-ENV:Body> 
<cxmla:ExecuteResponse xmlns:cxmla="urn:schemas-microsoft-com:xml-analysis"> 
<cxmla:return> 
<root xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:EX="urn:schemas-microsoft-com:xml-analysis:exception"> 
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:schemas-microsoft-com:xml-analysis:mddataset" xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sql="urn:schemas-microsoft-com:xml-sql" elementFormDefault="qualified"> 
<xsd:complexType name="MemberType"> 
<xsd:sequence> 
<xsd:element name="UName" type="xsd:string"/> 
<xsd:element name="Caption" type="xsd:string"/> 
<xsd:element name="LName" type="xsd:string"/> 
<xsd:element name="LNum" type="xsd:unsignedInt"/> 
<xsd:element name="DisplayInfo" type="xsd:unsignedInt"/> 
     <xsd:sequence maxOccurs="unbounded" minOccurs="0"> 
      <xsd:any processContents="lax" maxOccurs="unbounded"/> 
     </xsd:sequence> 
     </xsd:sequence> 
     <xsd:attribute name="Hierarchy" type="xsd:string"/> 
    </xsd:complexType> 
    <xsd:complexType name="PropType"> 
     <xsd:attribute name="name" type="xsd:string"/> 
    </xsd:complexType> 
    <xsd:complexType name="TupleType"> 
     <xsd:sequence maxOccurs="unbounded"> 
     <xsd:element name="Member" type="MemberType"/> 
     </xsd:sequence> 
    </xsd:complexType> 
    <xsd:complexType name="MembersType"> 
     <xsd:sequence maxOccurs="unbounded"> 
     <xsd:element name="Member" type="MemberType"/> 
     </xsd:sequence> 
     <xsd:attribute name="Hierarchy" type="xsd:string"/> 
    </xsd:complexType> 
    <xsd:complexType name="TuplesType"> 
     <xsd:sequence maxOccurs="unbounded"> 
     <xsd:element name="Tuple" type="TupleType"/> 
     </xsd:sequence> 
    </xsd:complexType> 
    <xsd:complexType name="CrossProductType"> 
     <xsd:sequence> 
     <xsd:choice minOccurs="0" maxOccurs="unbounded"> 
      <xsd:element name="Members" type="MembersType"/> 
      <xsd:element name="Tuples" type="TuplesType"/> 
     </xsd:choice> 
     </xsd:sequence> 
     <xsd:attribute name="Size" type="xsd:unsignedInt"/> 
    </xsd:complexType> 
    <xsd:complexType name="OlapInfo"> 
     <xsd:sequence> 
     <xsd:element name="CubeInfo"> 
      <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element name="Cube" maxOccurs="unbounded"> 
       <xsd:complexType> 
        <xsd:sequence> 
        <xsd:element name="CubeName" type="xsd:string"/> 
        </xsd:sequence> 
       </xsd:complexType> 
       </xsd:element> 
      </xsd:sequence> 
      </xsd:complexType> 
     </xsd:element> 
     <xsd:element name="AxesInfo"> 
      <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element name="AxisInfo" maxOccurs="unbounded"> 
       <xsd:complexType> 
        <xsd:sequence> 
        <xsd:element name="HierarchyInfo" minOccurs="0" maxOccurs="unbounded"> 
         <xsd:complexType> 
         <xsd:sequence> 
          <xsd:sequence maxOccurs="unbounded"> 
          <xsd:element name="UName" type="PropType"/> 
          <xsd:element name="Caption" type="PropType"/> 
          <xsd:element name="LName" type="PropType"/> 
          <xsd:element name="LNum" type="PropType"/> 
          <xsd:element name="DisplayInfo" type="PropType" minOccurs="0" maxOccurs="unbounded"/> 
          </xsd:sequence> 
          <xsd:sequence> 
          <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/> 
          </xsd:sequence> 
         </xsd:sequence> 
         <xsd:attribute name="name" type="xsd:string" use="required"/> 
         </xsd:complexType> 
        </xsd:element> 
        </xsd:sequence> 
        <xsd:attribute name="name" type="xsd:string"/> 
       </xsd:complexType> 
       </xsd:element> 
      </xsd:sequence> 
      </xsd:complexType> 
     </xsd:element> 
     <xsd:element name="CellInfo"> 
      <xsd:complexType> 
      <xsd:sequence> 
       <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
       <xsd:choice> 
        <xsd:element name="Value" type="PropType"/> 
        <xsd:element name="FmtValue" type="PropType"/> 
        <xsd:element name="BackColor" type="PropType"/> 
        <xsd:element name="ForeColor" type="PropType"/> 
        <xsd:element name="FontName" type="PropType"/> 
        <xsd:element name="FontSize" type="PropType"/> 
        <xsd:element name="FontFlags" type="PropType"/> 
        <xsd:element name="FormatString" type="PropType"/> 
        <xsd:element name="NonEmptyBehavior" type="PropType"/> 
        <xsd:element name="SolveOrder" type="PropType"/> 
        <xsd:element name="Updateable" type="PropType"/> 
        <xsd:element name="Visible" type="PropType"/> 
        <xsd:element name="Expression" type="PropType"/> 
       </xsd:choice> 
       </xsd:sequence> 
       <xsd:sequence maxOccurs="unbounded" minOccurs="0"> 
       <xsd:any processContents="lax" maxOccurs="unbounded"/> 
       </xsd:sequence> 
      </xsd:sequence> 
      </xsd:complexType> 
     </xsd:element> 
     </xsd:sequence> 
    </xsd:complexType> 
    <xsd:complexType name="Axes"> 
     <xsd:sequence maxOccurs="unbounded"> 
     <xsd:element name="Axis"> 
      <xsd:complexType> 
      <xsd:choice minOccurs="0" maxOccurs="unbounded"> 
       <xsd:element name="CrossProduct" type="CrossProductType"/> 
       <xsd:element name="Tuples" type="TuplesType"/> 
       <xsd:element name="Members" type="MembersType"/> 
      </xsd:choice> 
      <xsd:attribute name="name" type="xsd:string"/> 
      </xsd:complexType> 
     </xsd:element> 
     </xsd:sequence> 
    </xsd:complexType> 
    <xsd:complexType name="CellData"> 
     <xsd:sequence> 
     <xsd:element name="Cell" minOccurs="0" maxOccurs="unbounded"> 
      <xsd:complexType> 
      <xsd:sequence maxOccurs="unbounded"> 
       <xsd:choice> 
       <xsd:element name="Value"/> 
       <xsd:element name="FmtValue" type="xsd:string"/> 
       <xsd:element name="BackColor" type="xsd:unsignedInt"/> 
       <xsd:element name="ForeColor" type="xsd:unsignedInt"/> 
       <xsd:element name="FontName" type="xsd:string"/> 
       <xsd:element name="FontSize" type="xsd:unsignedShort"/> 
       <xsd:element name="FontFlags" type="xsd:unsignedInt"/> 
       <xsd:element name="FormatString" type="xsd:string"/> 
       <xsd:element name="NonEmptyBehavior" type="xsd:unsignedShort"/> 
       <xsd:element name="SolveOrder" type="xsd:unsignedInt"/> 
       <xsd:element name="Updateable" type="xsd:unsignedInt"/> 
       <xsd:element name="Visible" type="xsd:unsignedInt"/> 
       <xsd:element name="Expression" type="xsd:string"/> 
       </xsd:choice> 
      </xsd:sequence> 
      <xsd:attribute name="CellOrdinal" type="xsd:unsignedInt" use="required"/> 
      </xsd:complexType> 
     </xsd:element> 
     </xsd:sequence> 
    </xsd:complexType> 
    <xsd:element name="root"> 
     <xsd:complexType> 
     <xsd:sequence maxOccurs="unbounded"> 
      <xsd:element name="OlapInfo" type="OlapInfo"/> 
      <xsd:element name="Axes" type="Axes"/> 
      <xsd:element name="CellData" type="CellData"/> 
     </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
    </xsd:schema> 
    <OlapInfo> 
    <CubeInfo> 
     <Cube> 
     <CubeName>Sales</CubeName> 
     </Cube> 
    </CubeInfo> 
    <AxesInfo> 
     <AxisInfo name="Axis0"> 
     <HierarchyInfo name="Measures"> 
      <UName name="[Measures].[MEMBER_UNIQUE_NAME]"/> 
      <Caption name="[Measures].[MEMBER_CAPTION]"/> 
      <LName name="[Measures].[LEVEL_UNIQUE_NAME]"/> 
      <LNum name="[Measures].[LEVEL_NUMBER]"/> 
      <DisplayInfo name="[Measures].[DISPLAY_INFO]"/> 
     </HierarchyInfo> 
     </AxisInfo> 
    </AxesInfo> 
    <CellInfo> 
     <Value name="VALUE"/> 
     <FmtValue name="FORMATTED_VALUE"/> 
     <FormatString name="FORMAT_STRING"/> 
    </CellInfo> 
    </OlapInfo> 
    <Axes> 
    <Axis name="Axis0"> 
     <Tuples> 
     <Tuple> 
      <Member Hierarchy="Measures"> 
      <UName>[Measures].[Unit Sales]</UName> 
      <Caption>Unit Sales</Caption> 
      <LName>[Measures].[MeasuresLevel]</LName> 
      <LNum>0</LNum> 
      <DisplayInfo>0</DisplayInfo> 
      </Member> 
     </Tuple> 
     </Tuples> 
    </Axis> 
    </Axes> 
    <CellData> 
    <Cell CellOrdinal="0"> 
     <Value xsi:type="xsd:double">266773</Value> 
     <FmtValue>266,773</FmtValue> 
     <FormatString>Standard</FormatString> 
    </Cell> 
    </CellData> 
</root> 
</cxmla:return> 
</cxmla:ExecuteResponse> 
</SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

我的目標是提取而來的CellData元素中的所有電池元件。雖然這個迴應只有一個單元格,但有可能多個單元格有更多的答案。我想使用XPath的,但我可能會丟失與命名空間的一些詳細登記:

$xml = simplexml_load_string($_rawResponse); 
$xml->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance'); 
$xml->registerXPathNamespace('cxmla', 'urn:schemas-microsoft-com:xml-analysis'); 
$_res = $xml->xpath('//CellData/Cell'); 
var_dump($_res); 

的var_dump的結果是:

array(0) { 
} 

,而不是像這樣:

array(1) { 
    [0]=> 
    object(SimpleXMLElement)#2 (4) { 
    ["@attributes"]=> 
    array(1) { 
     ["CellOrdinal"]=> 
     string(1) "0" 
    } 
    ["Value"]=> 
    string(4) "266773" 
    ["FmtValue"]=> 
    string(5) "266,773" 
    ["FormatString"]=> 
    string(8) "Standard" 
    } 
} 

我在做什麼錯?你能指出我正確的方向嗎?先謝謝你。

+0

如果轉儲整個解析的XML結構,您會得到什麼?你有沒有在那裏看到Cell元素?如果是這樣,它可能是你的XPath的問題;如果不是,那麼解析數據就是一個問題。 – qid 2011-12-15 18:47:35

+0

你有沒有考慮過使用[一個合適的soap libary](http://www.php.net/manual/en/soapclient.soapclient.php)呢? SOAP XML從未打算直接創建或解析 - 抽象層應該自動爲您提供本機數據類型中的某些內容。如果有WSDL,你的工作會變得更加複雜.... – 2011-12-16 00:37:55

+0

嗨,弗朗西斯。沒有WSDL,我也嘗試過在非WSDL模式下使用SoapClient,但問題會相同,因爲__doRequest方法會返回相同的XML字符串。 – 2011-12-19 17:27:30

回答

2

這是一個命名空間問題。

<root>元素,這是<CellData>元素的父,有一個默認的命名空間定義xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset"所以<CellData>是在名字空間(比如它的所有後代也恰巧是)。因此,您需要註冊該名稱空間併爲其指定一些前綴,然後在XPath步驟中使用該前綴。

$xml->registerXPathNamespace('md', 'urn:schemas-microsoft-com:xml-analysis:mddataset'); 
$_res = $xml->xpath('//md:CellData/md:Cell'); 

如果給定元素名稱未加前綴,則XPath查詢始終搜索不在任何名稱空間中的元素。