2011-12-15 3 views
1

나는 CURL을 사용하여 몬드리안에게 SOAP 요청을 보낸다.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 요소 내에 오는 모든 셀 요소를 추출하는이 CURL이 사용되는 PHP 코드입니다 . 이 응답은 단 하나의 셀만 제공되지만 더 많은 응답은 둘 이상의 셀이 포함될 가능성이 있습니다. 나는 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 구조를 덤프하는 경우 어떻게됩니까? 거기에 셀 요소가 보이십니까? 그렇다면 xpath에 문제가 될 수 있습니다. 그렇지 않다면 데이터 파싱에 문제가 있습니다. – qid

+0

대신에 [올바른 비누 용 서랍] (http://www.php.net/manual/en/soapclient.soapclient.php)을 사용해 보셨습니까? SOAP XML은 절대로 직접 생성되거나 파싱되지 않았습니다. 추상화 계층은 네이티브 데이터 유형으로 무언가를 자동으로 제공합니다. WSDL이 있다면 일이 더 쉬워집니다 .... –

+0

안녕하세요, Francis. WSDL이 없으며 비 WSDL 모드에서 SoapClient를 사용해 보았지만 __doRequest 메서드가 동일한 XML 문자열을 반환하므로 문제가 동일합니다. –

답변

2

이것은 네임 스페이스 문제입니다.

<CellData> 요소의 부모 인 <root> 요소는, (모든 후손도 될 일이 같은) 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 쿼리는 주어진 요소 이름이 접두어가 아닌 경우 항상 네임 스페이스에없는 요소를 검색합니다.

+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); 결과는 1이어야합니다. SOAP 및 Namespaces 항목이없는 유사한 XML 문자열을 구문 분석하여 정상적으로 작동했습니다. –