roy naufal
roy naufal

Reputation: 389

php parse xml document

I've been trying to parse this xml document to loop the 'table' element for the last 2 hours, but it's not working ! I've tried this mainly as reference but it's not working simplexml_load_string returns blank array

here's my XML, how can I loop through the 'table' node ?

    <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetMovieListResult xmlns="http://vista.co.nz/services/WSVistaWebClient.DataTypes/1/"><Result>OK</Result><DatasetXML><NewDataSet>
      <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
        <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
          <xs:complexType>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element name="Table">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Cinema_strID" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_strID" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_strName" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_strRating" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_strName_2" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_strRating_2" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_HOFilmCode" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_intFCode" type="xs:int" minOccurs="0" />
                    <xs:element name="CinOperator_strCode" type="xs:int" minOccurs="0" />
                    <xs:element name="CinOperator_strName" type="xs:int" minOccurs="0" />
                    <xs:element name="Event_strCode" type="xs:string" minOccurs="0" />
                    <xs:element name="Event_strFilmsIndependent" type="xs:string" minOccurs="0" />
                    <xs:element name="MemberMovie" type="xs:string" minOccurs="0" />
                    <xs:element name="HOPK" type="xs:string" minOccurs="0" />
                    <xs:element name="Movie_intList_Pos" type="xs:int" minOccurs="0" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:choice>
          </xs:complexType>
        </xs:element>
      </xs:schema>
      <Table>
        <Cinema_strID>0</Cinema_strID>
        <Movie_strID>0010000845</Movie_strID>
        <Movie_strName>BATMAN Vs SUPERMAN</Movie_strName>
        <Movie_strRating>PG13</Movie_strRating>
        <Movie_strName_2 />
        <Movie_strRating_2 />
        <Movie_HOFilmCode />
        <Movie_intFCode>0</Movie_intFCode>
        <Event_strCode />
        <MemberMovie>N</MemberMovie>
        <HOPK />
        <Movie_intList_Pos>50</Movie_intList_Pos>
      </Table>
      <Table>
        <Cinema_strID>0</Cinema_strID>
        <Movie_strID>0010000846</Movie_strID>
        <Movie_strName>BATMAN Vs SUPERMAN VIP</Movie_strName>
        <Movie_strRating>PG13</Movie_strRating>
        <Movie_strName_2 />
        <Movie_strRating_2 />
        <Movie_HOFilmCode />
        <Movie_intFCode>0</Movie_intFCode>
        <Event_strCode />
        <MemberMovie>N</MemberMovie>
        <HOPK />
        <Movie_intList_Pos>50</Movie_intList_Pos>
      </Table>

    </NewDataSet></DatasetXML></GetMovieListResult></soap:Body></soap:Envelope>

Upvotes: 1

Views: 96

Answers (1)

fusion3k
fusion3k

Reputation: 11689

Probably you have some issue with NameSpaceURIs.

NamespaceURIs are characterized by tags with colon (<soap:Envelope>) and by NamespaceURI declaration, an attribute (usually of root element) with “xmlns:” prefix:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" .... >
<!--           └──┬─┘└┬─┘  └────────────────────────┬──────────────┘
                  │   └──────┐                      │
   NameSpace Declaration   NameSpace Prefix   NameSpaceURI      -->

The main NameSpaceURI, applied to tags without prefix, is characterized by attribute “xmlns”, without comma.

To search for NameSpaceURI elements, you can use ->children(), using as argument relative NameSpaceURI:

$children = $xml->children( 'http://schemas.xmlsoap.org/soap/envelope/' );

or, adding optional parameter is_prefix_, the NameSpaceURI prefix:

$children = $xml->children( 'soap', True );

In your case, before accessing <Table>, you have to select direct parent node:

$xml = simplexml_load_file( $filePath );

$body               = $xml->children( 'soap', True );
$GetMovieListResult = $body->children();
$NewDataSet         = $GetMovieListResult->children()->DatasetXML->NewDataSet;
#                                                      └───────────────────┬┘
#                                         Here we can use standard syntax ─┘

At this point, we can catch, e.g., all movie names:

$movieNames = array[];
foreach( $NewDataSet->Table as $table )
{
    $movieNames[] = (string) $table->Movie_strName;
}

Now $movieNames array you have:

Array
(
    [0] => BATMAN Vs SUPERMAN
    [1] => BATMAN Vs SUPERMAN VIP
)

By this method, you can retrieve any other node value.


Using XPath

A more comfortable method is to use XPath, a syntax that uses path expressions to navigate in XML documents. To using XPath in a Namespaced XML, first we have to register the Namespace(s) that we want to use in the pattern:

$xml->registerXPathNamespace( 'xmlns', 'http://vista.co.nz/services/WSVistaWebClient.DataTypes/1/' );

In this case, I have registered main NameSpaceURI1. Then we can search for the pattern:

$tables = '//xmlns:Table';

The double slash at beginning of pattern means: “Search for nodes matching following pattern no matter where they are”2. Now, we have a set of nodes that we can iterate through as precedent example:

foreach( $tables as $table )
{
    (...)


Notes:

  1. We can use any characters combination registering NameSpaces, not necessarily that one used in the document. I.e. if I register main NS in this way: $xml->registerXPathNamespace( 'x', 'http://vista.co.nz/services/WSVistaWebClient.DataTypes/1/' );, then I can construct XPath pattern in this way: //x:Table.

  2. To search the exact descending tree, we can use / instead of //. In this case, however, we have to register all NameSpaces that appear in the tree.

Upvotes: 1

Related Questions