XML printing object (SimpleXMLElement) # 1 (0) {}

1

How to transform a xml into a array or object?

I make a request that returns me the following xml :

xmlteste.xml

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="https://www.twwwireless.com.br/reluzcap/wsreluzcap">
  <xs:schema id="OutDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="OutDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="BuscaSMS">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="seunum" type="xs:string" minOccurs="0" />
                <xs:element name="celular" type="xs:string" minOccurs="0" />
                <xs:element name="mensagem" type="xs:string" minOccurs="0" />
                <xs:element name="status" type="xs:string" minOccurs="0" />
                <xs:element name="datarec" type="xs:dateTime" minOccurs="0" />
                <xs:element name="dataenv" type="xs:dateTime" minOccurs="0" />
                <xs:element name="datastatus" type="xs:dateTime" minOccurs="0" />
                <xs:element name="op" type="xs:short" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <OutDataSet xmlns="">
      <BuscaSMS diffgr:id="BuscaSMS0" msdata:rowOrder="3">
        <seunum>999999999</seunum>
        <celular>9999999999</celular>
        <mensagem>obrigado</mensagem>
        <status>MO</status>
        <datarec>2018-02-01T13:30:51.547-02:00</datarec>
        <dataenv>2018-02-01T13:30:52.773-02:00</dataenv>
        <datastatus>2018-02-01T13:30:52.773-02:00</datastatus>
        <op>5</op>
      </BuscaSMS>
      <BuscaSMS diffgr:id="BuscaSMS1" msdata:rowOrder="4">
        <seunum>99999999999</seunum>
        <celular>9999999999</celular>
        <mensagem>Obrigado.</mensagem>
        <status>MO</status>
        <datarec>2018-02-01T13:37:17.18-02:00</datarec>
        <dataenv>2018-02-01T13:37:20.807-02:00</dataenv>
        <datastatus>2018-02-01T13:37:20.807-02:00</datastatus>
        <op>5</op>
      </BuscaSMS>
    </OutDataSet>
  </diffgr:diffgram>
</DataSet>

I tried to do the following:

$page = file_get_contents("http://localhost/xmlteste.xml");
$page = new SimpleXMLElement($page);
var_dump($page);

However, it always returns object (SimpleXMLElement) # 1 (0) {}. I also tried others like Convert XML to array in PHP ), but unfortunately nothing seems to work. Can anyone help?

I'm trying to turn it into array to loop through the data contained in tag <BuscaSMS>

    
asked by anonymous 05.02.2018 / 13:50

1 answer

3

TL; DR

  • var_dump will not necessarily display all nodes for SimpleXMLElement ;
  • If there is no error, it means the parse occurred and the SimpleXMLElement object was created;
  • You can use XPath to search for a specific node;
  • The library SimpleXML is somewhat limited. Libraries DOM or XML Parser are excellent alternatives.

Explanation

That's not why var_dump is not displaying the nodes it did not load . They are there, and can be checked if you use the SimpleXMLElement::asXML() method

It's important to note that although I use the simplexml_load_string method in examples below, using the SimpleXMLElement builder follows the same return rules. That in case of error, it will return false

  

Returns an object of class SimpleXMLElement with properties containing the data held within the XML document, or FALSE on failure .

There is no right explanation about the fact that it does not appear in var_dump (at least I did not find it), I just know it is related to the use of namespace prefixes.

If you remove all prefixes, you can view the entire object and its nodes in var_dump .

Navigation between nodes

However, the library SimpleXML is somewhat limited for the handling of complex XMLs, which this is the case you are trying. See the example below:

$simpleXml = simplexml_load_string($xml);
var_dump($simpleXml->children()->asXML());

Result:

bool(false)

Could not find any child for XML. Now see by setting a namespace prefix:

$simpleXml = simplexml_load_string($xml);
var_dump($simpleXml->children('diffgr' , true)->asXML());

Result:

string(1017) "<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <OutDataSet xmlns="">
      <BuscaSMS diffgr:id="BuscaSMS0" msdata:rowOrder="3">
        <seunum>999999999</seunum>
        <celular>9999999999</celular>
        <mensagem>obrigado</mensagem>
        <status>MO</status>
        <datarec>2018-02-01T13:30:51.547-02:00</datarec>
        <dataenv>2018-02-01T13:30:52.773-02:00</dataenv>
        <datastatus>2018-02-01T13:30:52.773-02:00</datastatus>
        <op>5</op>
      </BuscaSMS>
      <BuscaSMS diffgr:id="BuscaSMS1" msdata:rowOrder="4">
        <seunum>99999999999</seunum>
        <celular>9999999999</celular>
        <mensagem>Obrigado.</mensagem>
        <status>MO</status>
        <datarec>2018-02-01T13:37:17.18-02:00</datarec>
        <dataenv>2018-02-01T13:37:20.807-02:00</dataenv>
        <datastatus>2018-02-01T13:37:20.807-02:00</datastatus>
        <op>5</op>
      </BuscaSMS>
    </OutDataSet>
  </diffgr:diffgram>"

So that you do not have to manually define each namespace you are looking for, you can use the SimpleXMLElement::getNamespaces() which will bring you all the XML namespaces :

$simpleXml = simplexml_load_string($xml);    
var_dump($simpleXml->getNamespaces(true));

Result:

array(3) {
  ["xs"]=>
  string(32) "http://www.w3.org/2001/XMLSchema"
  ["msdata"]=>
  string(36) "urn:schemas-microsoft-com:xml-msdata"
  ["diffgr"]=>
  string(41) "urn:schemas-microsoft-com:xml-diffgram-v1"
}

And so you can use SimpleXML to access and navigate through each XML node .

Search

Since you just want to access the% nodes BuscaSMS , you can use the search through XPath for such a solution using the SimpleXMLElement::xpath() method:

$simpleXml = simplexml_load_string($xml);
var_dump($simpleXml->xpath('//BuscaSMS'));

Result:

array(2) {
  [0]=>
  object(SimpleXMLElement)#2 (8) {
    ["seunum"]=>
    string(9) "999999999"
    ["celular"]=>
    string(10) "9999999999"
    ["mensagem"]=>
    string(8) "obrigado"
    ["status"]=>
    string(2) "MO"
    ["datarec"]=>
    string(29) "2018-02-01T13:30:51.547-02:00"
    ["dataenv"]=>
    string(29) "2018-02-01T13:30:52.773-02:00"
    ["datastatus"]=>
    string(29) "2018-02-01T13:30:52.773-02:00"
    ["op"]=>
    string(1) "5"
  }
  [1]=>
  object(SimpleXMLElement)#3 (8) {
    ["seunum"]=>
    string(11) "99999999999"
    ["celular"]=>
    string(10) "9999999999"
    ["mensagem"]=>
    string(9) "Obrigado."
    ["status"]=>
    string(2) "MO"
    ["datarec"]=>
    string(28) "2018-02-01T13:37:17.18-02:00"
    ["dataenv"]=>
    string(29) "2018-02-01T13:37:20.807-02:00"
    ["datastatus"]=>
    string(29) "2018-02-01T13:37:20.807-02:00"
    ["op"]=>
    string(1) "5"
  }
}

Practical example this link .

Other libraries

Anyway, I recommend using some other XML manipulation library , such as DOM or XML Parser . In this link you can view the use of the DOM " with your XML. There is no need for namespace definitions, just use it.

Since you'd like to find node BuscaSMS , just use the DOMDocument::getElementsByTagName() method. .

$dom = new \DOMDocument();
$dom->loadXML($xml);
foreach($dom->getElementsByTagName('BuscaSMS') as $buscaSMS)
{
    var_dump($buscaSMS);
}

You can view the result in this link

In this link , you can read a basic explanation of using the DOM library.

    
06.02.2018 / 12:14