How to parse a SOAP XML response with Namespaces using PHP and SimpleXML

隐身守侯 提交于 2019-12-13 19:15:43

问题


I'm using CURL to send a SOAP request to Mondrian. This is the PHP code where CURL is being used:

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

The received SOAP response I get from Mondrian is:

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

My objective is to extract all the Cell elements that come inside the CellData element. Although this response comes with only one Cell, it is possible that further answers come with more than one. I was thinking of using XPath, but I may be missing some detail related to Namespace registering:

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

The result of var_dump is:

array(0) {
}

instead of something like:

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"
  }
}

What am I doing wrong? Could you point me in the right direction ? Thank you in advance.


回答1:


This is a namespace issue.

The <root> element, which is the parent of the <CellData> element, has a default namespace definition xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset" so <CellData> is in that namespace (like all its descendants also happen to be). Therefore you need to register this namespace and give it some prefix and then use that prefix in your XPath steps.

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

XPath queries always search for an element that is not in any namespace if the given element name is not prefixed.




回答2:


Using DOMDocument you can get all values in xml. Try with DOMDocument Documentation Link: http://php.net/manual/en/class.domdocument.php



来源:https://stackoverflow.com/questions/8525020/how-to-parse-a-soap-xml-response-with-namespaces-using-php-and-simplexml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!