Как проанализировать XML-ответ SOAP с пространствами имен, используя PHP и SimpleXML - PullRequest
1 голос
/ 15 декабря 2011

Я использую CURL для отправки SOAP-запроса к Мондриану. Это код PHP, где используется CURL:

$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>

Моя цель - извлечь все элементы Cell, которые находятся внутри элемента 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"
  }
}

Что я делаю не так? Не могли бы вы указать мне правильное направление? Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 16 декабря 2011

Это проблема пространства имен.

Элемент <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 всегда ищут элемент, который не находится ни в каком пространстве имен, если данное имя элементабез префикса.

0 голосов
/ 15 декабря 2011

Используя DOMDocument, вы можете получить все значения в xml. Попробуйте с DOMDocument Documentation Link: http://php.net/manual/en/class.domdocument.php

...