PHP parsing error

Hi,

Working on my first piece of PHP code, but run into a problem I can't work out.

Code is supposed to pull each users settings from a server, and process each one. It does two users, then gives the error


445203" BackupSetName="Sue" UploadSize="3112" RunVersion="6.7.2.0"/></BackupJobs>PHP Fatal error: Uncaught exception 'Exception' with

message 'String could not be parsed as XML' in C:\Documents and Settings\TEMP\Desktop\script\faulty.php:25
Stack trace:
#0 C:\Documents and Settings\TEMP\Desktop\script\faulty.php(25): SimpleXMLElement->__construct('')
#1 {main} thrown in C:\Documents and Settings\TEMP\Desktop\script\faulty.php on line 25



This is the code I am using, I can't give the login details for the server, but perhaps someone can see something obvious?



<?php

$SysUser='';
$SysPassword='';
$ServerAddy='';
$i=0;



$url='http://'.$ServerAddy.'/obs/api/ListUsers.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword;
$rt=get_data($url); //dumps the content, you can manipulate as you wish to

$doc=new SimpleXMLElement($rt);

foreach($doc->User as $data1){
//echo $data1['LoginName'].',';
$user[$i]['LoginName'] = $data1['LoginName'];
$user[$i]['Name1'] = $data1->Contact[0]['Name'];
$user[$i]['Email1'] = $data1->Contact[0]['Email'];

$url='http://'.$ServerAddy.'/obs/api/ListBackupJobStatus.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword.'&BackupDate=2011-12-30&LoginName='.$data1'LoginName'];
$rt=get_data($url); //dumps the content, you can manipulate as you wish to

print_r($rt);
$doc=new SimpleXMLElement($rt);
$user[$i]['ID0'] = $doc->BackupJob[0]['ID'];
$user[$i]['StartTime0'] = $doc->BackupJob[0]['StartTime'];
$user[$i]['EndTime0'] = $doc->BackupJob[0]['EndTime'];
$user[$i]['BackupSetName0'] = $doc->BackupJob[0]['BackupSetName'];
$user[$i]['BackupJobStatus0'] = $doc->BackupJob[0]['BackupJobStatus'];
$user[$i]['BackupSetID0'] = $doc->BackupJob[0]['BackupSetID'];
$user[$i]['ID1'] = $doc->BackupJob[1]['ID'];
$user[$i]['StartTime1'] = $doc->BackupJob[1]['StartTime'];
$user[$i]['EndTime1'] = $doc->BackupJob[1]['EndTime'];
$user[$i]['BackupSetName1'] = $doc->BackupJob[1]['BackupSetName'];
$user[$i]['BackupJobStatus1'] = $doc->BackupJob[1]['BackupJobStatus'];
$user[$i]['BackupSetID1'] = $doc->BackupJob[1]['BackupSetID'];



$i++;
}


function get_data($url)
{
$ch = curl_init();
$timeout = 1000;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;

}
?>



As I say, it processes the first two users properly, but gives the error after that. When I run the script, the line print_r($rt); shows me the first two users information, but then gives the error after that.

I have removed the line $doc=new SimpleXMLElement($rt); and I can see each users information coming through, but of course now it doesn't do anything with it. I've scanned the third users data, and it is no different to any of the others, and I've tried running the data manually, ie, making rt$= the string of data manually, and it goes through fine, but just won't do it automatically.

Any ideas?

Many thanks.
whittanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Sudaraka WijesingheWeb Application ProgrammerCommented:
Please post your XML here. Also make sure it doesn't have any errors.
0
NetExpert-WarszawaCommented:
SimpleXMLElement tries to parse some XML and fails. It looks like the XML has got a wrong structure. Verify it here: http://www.w3schools.com/dom/dom_validate.asp
0
whittanAuthor Commented:
The xml is generated dynamically from the server. An example is below which verifys fine in the validate above.

When I run the system, it pulls the first couple of users data, then fails on the third. On another server, it fails on the first.



<BackupJobs BackupDate="2011-12-30" ><BackupJob ID="2011-12-30-00-00-00" LoginName="whittan" Owner="" UserId="whittan" StartTime="2011-12-30 06:56:06" EndTime="2011-12-30 06:56:06" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1320821918202" BackupSetName="Laptop Email" UploadSize="0" RunVersion=""/><BackupJob ID="2011-12-30-00-00-00" LoginName="whittan" Owner="" UserId="whittan" StartTime="2011-12-30 06:56:00" EndTime="2011-12-30 06:56:00" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1291441536625" BackupSetName="Abby" UploadSize="0" RunVersion=""/><BackupJob ID="2011-12-30-00-30-00" LoginName="whittan" Owner="" UserId="whittan" StartTime="2011-12-30 06:56:02" EndTime="2011-12-30 06:56:02" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1300936373640" BackupSetName="Email" UploadSize="0" RunVersion=""/><BackupJob ID="2011-12-29-21-00-00" LoginName="whittan" Owner="" UserId="whittan" StartTime="2011-12-30 03:56:04" EndTime="2011-12-30 03:56:04" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1313796307171" BackupSetName="BackupSet" UploadSize="0" RunVersion=""/><BackupJob ID="2011-12-30-01-30-00" LoginName="whittan" Owner="" UserId="whittan" StartTime="2011-12-30 07:56:02" EndTime="2011-12-30 07:56:02" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1300936249937" BackupSetName="Other Files" UploadSize="0" RunVersion=""/><BackupJob ID="2011-12-30-01-00-00" LoginName="whittan" Owner="" UserId="whittan" StartTime="2011-12-30 07:56:00" EndTime="2011-12-30 07:56:00" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1297984955828" BackupSetName="MyDocs and Favourites" UploadSize="0" RunVersion=""/></BackupJobs>

0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

NetExpert-WarszawaCommented:
Catch a user for which it fails. Check for any special characters in string fields. I expect some quotations marks, angle brackets, ampersands or slashes that are not escaped
0
whittanAuthor Commented:
Yes, thats why I'm stumped. If you comment out the line $doc=new SimpleXMLElement($rt); it runs through all the users. I've dumped them into a file, then checked each user through the xml verify link above, and they are all clean.
0
NetExpert-WarszawaCommented:
Is the XML you have given the one for which it fails? Is it the output of the line with print_r executed just before the exception?

You can simplify the code to:
<?php
$xml = 'paste XML here';
$doc=new SimpleXMLElement($xml);
?>

Open in new window


Just paste each XML string in the first line and check if SimpleXMLElement fail.

Another idea:
You do not test a curl_exec return value. It is false on failure (wrong url, timeout etc.). Then you give false to SimpleXMLElement for which it is not a valid input.
0
whittanAuthor Commented:
I've also run each users data separately through the script, by making $rt='xmlcode'; just above print_r($rt); and each users code runs through fine. It only errors when I try and run the script with the users data automatically generated one after the other.
0
NetExpert-WarszawaCommented:
Replace the line:
$data = curl_exec($ch);

Open in new window


with:
$data = curl_exec($ch);
if($data === false) {
  throw new Exception('A problem with curl');
}

Open in new window

0
whittanAuthor Commented:
Thanks, still gives same problem :(

C:\script>php cutdown.php
PHP Fatal error:  Uncaught exception 'Exception' with message 'String could not
be parsed as XML' in C:\script\cutdown.php:36
Stack trace:
#0 C:\script\cutdown.php(36): SimpleXMLElement->__construct('')
#1 {main}
  thrown in C:\script\cutdown.php on line 36

C:\script>pause
0
whittanAuthor Commented:
Ive changed the code to

$rt=get_data($url); //dumps the content, you can manipulate as you wish to

$fg = fopen("file3.txt", "a");
fwrite($fg, $rt);
fclose($fg);

print_r($rt);
//$doc=new SimpleXMLElement($rt);


The contents of "file3.txt" are

<BackupJobs BackupDate="2011-12-30" ><BackupJob ID="2011-12-30-01-00-06" LoginName="To" Owner="" UserId="To" StartTime="2011-12-30 01:03:55" EndTime="2011-12-30 01:04:01" BackupJobStatus="BS_STOP_SUCCESS_WITH_WARNING" BackupSetID="1310984061187" BackupSetName="Accounts" UploadSize="0" RunVersion="6.7.0.0"/><BackupJob ID="2011-12-30-04-00-00" LoginName="To" Owner="" UserId="To" StartTime="2011-12-30 04:03:30" EndTime="2011-12-30 04:04:49" BackupJobStatus="BS_STOP_SUCCESS" BackupSetID="1310465319079" BackupSetName="Mysql PR Visual" UploadSize="1216816" RunVersion="6.7.0.0"/><BackupJob ID="2011-12-30-22-30-07" LoginName="To" Owner="" UserId="To" StartTime="2011-12-30 22:33:37" EndTime="2011-12-30 22:34:21" BackupJobStatus="BS_STOP_SUCCESS" BackupSetID="1310464489079" BackupSetName="To" UploadSize="0" RunVersion="6.7.0.0"/></BackupJobs><BackupJobs BackupDate="2011-12-30" ><BackupJob ID="2011-12-30-21-15-05" LoginName="Pa" Owner="" UserId="Pa" StartTime="2011-12-30 21:18:32" EndTime="2011-12-30 21:18:41" BackupJobStatus="BS_STOP_SUCCESS" BackupSetID="1307268743664" BackupSetName="Pa" UploadSize="0" RunVersion="6.7.0.0"/></BackupJobs><BackupJobs BackupDate="2011-12-30" ><BackupJob ID="2011-12-30-22-40-01" LoginName="Sw" Owner="" UserId="Sw" StartTime="2011-12-30 22:43:36" EndTime="2011-12-30 22:44:04" BackupJobStatus="BS_STOP_SUCCESS" BackupSetID="1307442518397" BackupSetName="Standard" UploadSize="0" RunVersion="6.7.0.0"/></BackupJobs><BackupJobs BackupDate="2011-12-30" ><BackupJob ID="2011-12-30-12-00-00" LoginName="ACo" Owner="" UserId="ACo" StartTime="2011-12-30 18:56:00" EndTime="2011-12-30 18:56:00" BackupJobStatus="BS_STOP_MISSED_BACKUP" BackupSetID="1311066645627" BackupSetName="Data" UploadSize="0" RunVersion=""/></BackupJobs><BackupJobs BackupDate="2011-12-30" ></BackupJobs>
0
NetExpert-WarszawaCommented:
Ok. We need to be sure what data causes the exception.

remove the line (to clean an output):
print_r($rt);

Open in new window


Replace the lines (both - we do not know which one causes the exception):
$doc=new SimpleXMLElement($rt);

Open in new window


with:
try {
  $doc=new SimpleXMLElement($rt);
} catch (Exception e) {
  echo '<div style="border:1px solid red;">';
  var_dump($rt);
  echo '</div>';
  exit;
}

Open in new window


Have you added curl return value testing? No errors?

One more thing (should not be a reason for the problem) - Are you sure you want to base a foreach loop on $doc->User and assign a new value to $doc inside?
0
whittanAuthor Commented:
Hi,

Code I am now using is below, but gives an error,  can you plz check those lines of code?

The curl return value testing didn't give any errors.

The foreach loop seems to work ok when it does work, but this bit of the code was given to me by someone else, so might not be appropriate. Is there a suggestion for somethine different / better?

Error whent he script below is run is:

C:\script>php cutdown.php
PHP Parse error:  syntax error, unexpected T_STRING, expecting T_VARIABLE in C:\
script\cutdown.php on line 15

C:\script>pause



<?php

$SysUser='removedforsecurity';
$SysPassword='password';
$ServerAddy='address';
$i=0;



$url='http://'.$ServerAddy.'/obs/api/ListUsers.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword;
$rt=get_data($url); //dumps the content, you can manipulate as you wish to

try {
  $doc=new SimpleXMLElement($rt);
} catch (Exception e) {
  echo '<div style="border:1px solid red;">';
  var_dump($rt);
  echo '</div>';
  exit;
}


foreach($doc->User as $data1){
//echo $data1['LoginName'].',';
$user[$i]['LoginName'] = $data1['LoginName'];
$user[$i]['Name1'] = $data1->Contact[0]['Name'];
$user[$i]['Email1'] = $data1->Contact[0]['Email'];

$url='http://'.$ServerAddy.'/obs/api/ListBackupJobStatus.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword.'&BackupDate=2011-12-30&LoginName='.$data1['LoginName'];

$rt=get_data($url); //dumps the content, you can manipulate as you wish to


\\$fg = fopen("file3.txt", "a");
\\fwrite($fg, $rt);
\\fclose($fg);


try {
  $doc=new SimpleXMLElement($rt);
} catch (Exception e) {
  echo '<div style="border:1px solid red;">';
  var_dump($rt);
  echo '</div>';
  exit;
}


$user[$i]['ID0'] = $doc->BackupJob[0]['ID'];
$user[$i]['StartTime0'] = $doc->BackupJob[0]['StartTime'];
$user[$i]['EndTime0'] = $doc->BackupJob[0]['EndTime'];
$user[$i]['BackupSetName0'] = $doc->BackupJob[0]['BackupSetName'];
$user[$i]['BackupJobStatus0'] = $doc->BackupJob[0]['BackupJobStatus'];
$user[$i]['BackupSetID0'] = $doc->BackupJob[0]['BackupSetID'];
$user[$i]['ID1'] = $doc->BackupJob[1]['ID'];
$user[$i]['StartTime1'] = $doc->BackupJob[1]['StartTime'];
$user[$i]['EndTime1'] = $doc->BackupJob[1]['EndTime'];
$user[$i]['BackupSetName1'] = $doc->BackupJob[1]['BackupSetName'];
$user[$i]['BackupJobStatus1'] = $doc->BackupJob[1]['BackupJobStatus'];
$user[$i]['BackupSetID1'] = $doc->BackupJob[1]['BackupSetID'];



$i++;
}


function get_data($url)
{
$ch = curl_init();
$timeout = 1000;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
if($data === false) {
  throw new Exception('A problem with curl');
}

curl_close($ch);
return $data;

}
?>
0
whittanAuthor Commented:
I changed e to $e (hope that was right) and got the output below when running the code. I'm not too sure exactly what I'm looking for:

C:\script>php cutdown.php
<div style="border:1px solid red;">string(0) ""
</div>
C:\script>pause
Press any key to continue . . .

I am running this from a command prompt in windows?
0
whittanAuthor Commented:
I've changed that bit of code to:

try {
  $doc=new SimpleXMLElement($rt);
} catch (Exception $e) {
  echo '<div style="border:1px solid red;">';
  var_dump($e);
  echo '</div>';
  exit;
}

In both places, and got the output

C:\script>php cutdown.php
<div style="border:1px solid red;">object(Exception)#7 (6) {
  ["message:protected"]=>
  string(33) "String could not be parsed as XML"
  ["string:private"]=>
  string(0) ""
  ["code:protected"]=>
  int(0)
  ["file:protected"]=>
  string(21) "C:\script\cutdown.php"
  ["line:protected"]=>
  int(35)
  ["trace:private"]=>
  array(1) {
    [0]=>
    array(6) {
      ["file"]=>
      string(21) "C:\script\cutdown.php"
      ["line"]=>
      int(35)
      ["function"]=>
      string(11) "__construct"
      ["class"]=>
      string(16) "SimpleXMLElement"
      ["type"]=>
      string(2) "->"
      ["args"]=>
      array(1) {
        [0]=>
        string(0) ""
      }
    }
  }
}
</div>
C:\script>pause
Press any key to continue . . .
0
NetExpert-WarszawaCommented:
Sure should be $e. My mistake.

Now you have got a cause. SimpleXMLElement does not like an empty string - var_dump showed string(0) "". You can see it in a dump of the exception too.

Quick and dirty solution would be to test $rt before calling a SimpleXMLElement constructor. However I strongly suggest to check for what url and why curl gives an empty string.
0
whittanAuthor Commented:
Thanks for that. Could you tell me how to "test" $rt? Can I run a command on it to remove the empty string before processing by SimpleXMLElement? There is nothing I can do about the data being generated by the URL, ie, how it comes out of the server.
0
NetExpert-WarszawaCommented:
Something like:
if(strlen($rt) > 0) {
  $doc=new SimpleXMLElement($rt);
  $user[$i]['ID0'] = $doc->BackupJob[0]['ID'];
  $user[$i]['StartTime0'] = $doc->BackupJob[0]['StartTime'];
  $user[$i]['EndTime0'] = $doc->BackupJob[0]['EndTime'];
  ...
}

Open in new window

0
whittanAuthor Commented:
I see.

So, the get_data function is returning an empty string? That is, $rt =  nothing at the time of the error? What would be the cause of that?
0
NetExpert-WarszawaCommented:
Not nothing - an empty string :)

Cause? The server returns nothing. To check why, first see for what URL it happens.

After
$data = curl_exec($ch);

Open in new window


add
if(strlen($data) == 0) {
  echo 'The URL causing problems is ' . $url;
}

Open in new window


Then verify that the URL is valid and makes sense.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
whittanAuthor Commented:
Hi,

Many thanks for helping us out. I believe the problem happens in line http://'.$ServerAddy.'/obs/api/ListUsers.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword; which can produce a tag for example LoginName="Test User Name". Note the spaces in the name.
 
It would appear simpleXML won't parse the spaces, throws out an empty string, which then upsets the line 'http://'.$ServerAddy.'/obs/api/ListBackupJobStatus.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword.'&BackupDate=2011-12-30&LoginName='.$data1'LoginName'];

Just need to figure out how to handle the usernames with spaces now, so that I don't loose that line of information :)

Cheers.
0
whittanAuthor Commented:
All fixed, added line $data1['LoginName'] = str_replace (" ", "%20", $data1['LoginName']); before line $url='http://'.$ServerAddy.'/obs/api/ListBackupJobStatus.do?SysUser='.$SysUser.'&SysPwd='.$SysPassword.'&BackupDate=2011-12-30&LoginName='.$data1'LoginName'];

Works great. Many thanks for your help :)
0
NetExpert-WarszawaCommented:
Use urlencode instead. Spaces may be not the only characters you can find in login names that cannot appear in URLs.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.