2011-12-15 24 views
1

私はCANDを使用してMondrianにSOAPリクエストを送信しています。これはCURLが使用されている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要素の内側に来るすべてのCell要素を抽出することです。このレスポンスは1つのセルのみで提供されますが、それ以上の回答が複数のセルに含まれる可能性もあります。私は、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

+0

代わりに[適切なsoap libary](http://www.php.net/manual/en/soapclient.soapclient.php)を使用することを検討しましたか? SOAP XMLは、決して直接作成または解析されることは意図されていませんでした。抽象レイヤーは、ネイティブデータ型で何かを自動的に提供することになっています。 WSDLがあれば、あなたの仕事はさらに楽になります.... –

+0

こんにちは、フランシス。 WSDLはありません。また、非WSDLモードでSoapClientを使用しようとしましたが、__doRequestメソッドが同じXML文字列を返すため、問題は同じになります。 –

答えて

2

これは名前空間の問題です。 <CellData>要素の親である

<root>要素は、<CellData>ので、デフォルトの名前空間の定義xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset"を持っている(そのすべての子孫でもあることが起こるように)その名前空間です。したがって、この名前空間を登録して接頭辞を与え、その接頭辞をXPathのステップで使用する必要があります。

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

XPathクエリは、指定された要素名が接頭辞でない場合、常に任意の名前空間にない要素を検索します。

+0

ありがとう、jasso、それは本当に名前空間の問題でした。 –

-2

DOMDocumentを使用すると、xmlのすべての値を取得できます。 DOMDocumentのドキュメントを参照してくださいリンク:http://php.net/manual/en/class.domdocument.php

+0

ありがとうございます。残念ながら、私はその解決策に大したことはありません: $ domdoc = new DOMDocument(); $ domdoc-> loadXML($ _ res); $ xpath =新しいDOMXPath($ domdoc); $ xpath-> registerNamespace( 'xsi'、 'http://www.w3.org/2001/XMLSchema-instance');$ xpath-> registerNamespace( 'cxmla'、 'urn:schemas-microsoft-com:xml-analysis'); $ res = $ xpath-> query( '// CellData/Cell'); printf($ res-> length。PHP_EOL); 結果は0、1になるはずです。私はSOAPとNamespacesのものを使わずに同様のXML文字列を解析してうまくいきました。 –

関連する問題