XML printing Object(Simplexmlelement)#1 (0) { }

Asked

Viewed 1,038 times

1

How to transform a xml in a array or object?

I make a request that returns to 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>

This is what I tried to do:

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

But it always returns Object(Simplexmlelement)#1 (0) { }. Besides I tried others like (Convert XML to PHP array), but unfortunately nothing seems to work. Someone can help?

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

1 answer

3


TL ; DR

  • var_dump not necessarily will display all of us to SimpleXMLElement;
  • If there is no error, it means the parse occurred and the object SimpleXMLElement was created;
  • Can use XPath to fetch a specific Node (node);
  • The library SimpleXML is somewhat limited. Libraries DOM or XML Parser are excellent alternatives.

Explanation

It’s not because the var_dump is not displaying the nodes they were not loaded. They are there, and can be checked if you use the method SimpleXMLElement::asXML()

It is important to note that although I use the method simplexml_load_string in the examples below, the use of the SimpleXMLElement follows the same rules of return. Which, in case of error, 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 for not appearing on var_dump (at least I have not located), just know that it is related to the use of prefixes namespace.

If you remove all prefixes, will be able to view the complete object, and its nodes, on var_dump.

Navigation between the nodes

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

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

Upshot:

bool(false)

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

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

Upshot:

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 don’t have to manually set each searched namespace, you can use the method SimpleXMLElement::getNamespaces() that will bring you all the namespaces of XML:

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

Upshot:

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 go using the SimpleXML to access and navigate through each XML node.

Research

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

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

Upshot:

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 at this link.

Other libraries

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

Since you would like to locate the Node BuscaSMS, just use the method DOMDocument::getElementsByTagName().

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

You can view the result on this link

At this link, you can read a basic explanation of the use of the library DOM.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.