PSN
PSN

Reputation: 99

How to convert PHP to XML output

I have a php code. this code outputs an HTML. I need to modify this code to output an XML. ANy ideas as to how shall I go about doing this. Is there any XML library available that directly does the job or do i have to manually create each node.?

My php code is:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<style>
a {text-decoration:none; color:black;}
</style>
</head>

<body>


<?php

$a=$_POST["title"];
$b=$_POST["name"];

$c="http://www.imdb.com/search/title?title=".urlencode($a)."&title_type=".urlencode($b);
$d=file_get_contents($c);


preg_match_all('/<div id="main">\n(No results.)/', $d,$nore);


preg_match_all('#<img src="(.*)"#Us', $d, $img);//image

preg_match_all('/<a\s*href="\/title\/tt[0-9]*\/">((?:[a-z]*(?:&*[.]*)?\s*-*[a-z]*[0-9]*[^<])+)/i',$d,$tit);  //title 

preg_match_all('/<span\sclass="year_type">\s*\(([\d]*)/',$d,$ye); //movie year working fine

preg_match_all('#<span class="credit">\n    Dir: (.*)\n(?:    With:)?#Us',$d,$dir); //director 

preg_match_all('/<span class="rating-rating"><span class="value">([\w]*.[\w]*)/i',$d,$rat); //rating 

preg_match_all('/<a\shref="(\/title\/tt[0-9]*\/)"\s*[title]+/i',$d,$lin); //link 




for($i=0;$i<5;$i++)
{ 
  if (@$rat[1][$i]=="-")
  $rat[1][$i]="N/A";
}

for($i=0;$i<5;$i++)
{ 
 if(@$dir[1][$i]=="")
 $dir[1][$i]="N/A";
}




if(count($tit[1])>5)
$cnt=5;
else
$cnt=count($tit[1]);



 echo"<center><b>Search Result</b></center>";
echo "<br/>";
echo "<center><b>\"$a\"of type\"$b\":</b></center>";
echo"<br/>";

if(@$nore[1][0]=="No results.")
echo "<center><b>No movies found!</b></center>";
else
{
echo "<center><table border=1><tr><td><center>Image</center></td><td><center>Title</center></td><td><center>Year</center></td><td><center>Director</center></td><td><center>Rating(10)</center></td><td><center>Link to Movie</center></td></tr>";
  for($j=0;$j<$cnt;$j++)
          {
            echo "<tr>";
            echo "<td>".@$img[0][$j+2]."</td>";
            echo "<td><center>".@$tit[1][$j]."</center></td>";
            echo "<td><center>".@$ye[1][$j]."</center></td>";
            echo "<td><center>".@$dir[1][$j]."</center></td>";
            echo "<td><center>".@$rat[1][$j]."</center></td>";
            echo '<td><center><a style="text-decoration:underline; color:blue;" href="http://www.imdb.com'.@$lin[1][$j].'">Details</a></center></td>';
            echo "</tr>";
          }




echo "</table></center>";
}               

?>

</body>
</html>

Expected XML output:

<result cover="http://ia.mediaimdb.com/images      
/M/MV5BMjMyOTM4MDMxNV5BMl5BanBnXkFtZTcwNjIyNzExOA@@._V1._SX54_
CR0,0,54,74_.jpg" title="The Amazing Spider-Man(2012)"year="2012"
director="Marc Webb" rating="7.5"
details="http://www.imdb.com/title/tt0948470"/>

<result cover="http://ia.mediaimdb.
com/images/M/MV5BMzk3MTE5MDU5NV5BMl5BanBnXkFtZTYwMjY3NTY3._V1._SX54_CR0,
0,54,74_.jpg" title="Spider-Man(2002)" year="2002"director="Sam Raimi"
rating="7.3" details="http://www.imdb.com/title/tt0145487"/>

<result cover="http://ia.mediaimdb.
com/images/M/MV5BODUwMDc5Mzc5M15BMl5BanBnXkFtZTcwNDgzOTY0MQ@@._V1._SX54_
CR0,0,54,74_.jpg" title="Spider-Man 3 (2007)" year="2007" director="Sam
Raimi" rating="6.3" details="http://www.imdb.com/title/tt0413300"/>

<result cover="http://i.mediaimdb.
com/images/SF1f0a42ee1aa08d477a576fbbf7562eed/realm/feature.gif" title="
The Amazing Spider-Man 2 (2014)" year="2014" director="Sam Raimi"
rating="6.3" details="http://www.imdb.com/title/tt1872181"/>

<result cover="http://ia.mediaimdb.
com/images/M/MV5BMjE1ODcyODYxMl5BMl5BanBnXkFtZTcwNjA1NDE3MQ@@._V1._SX54_
CR0,0,54,74_.jpg" title="Spider-Man 2 (2004)" year="2004" director="Sam
Raimi" rating="7.5" details="http://www.imdb.com/title/tt0316654"/>
</results>

Upvotes: 0

Views: 8798

Answers (1)

Tivie
Tivie

Reputation: 18923

First thing, you're parsing your html result with regex which is inefficient, unnecessary, and... well, you're answering to the cthulhu call!

Second, parsing IMDB HTML to retrieve results, although valid, might be unnecessary. There are some neat 3rd party APIs that do the job for you, like http://imdbapi.org

If you don't want to use any 3rd party API though, IMHO, you should, instead, parse the HTML using a DOM parser/manipulator, like DOMDocument, for instance, which is safer, better and, at the same time, can solve your HTML to XML problem.

Here's the bit you asked (build XML and HTML from results):

function resultsToHTML($results)
{
    $doc = new DOMDocumet();
    $table = $doc->createElement('table');

    foreach ($results as $r) {
        $row = $doc->createElement('tr');
        $doc->appendChild($row);
        $title = $doc->createElement('td', $r['title']);
        $row->appendChild($title);
        $year = $doc->createElement('td', $r['year']);
        $row->appendChild($year);
        $rating = $doc->createElement('td', $r['rating']);
        $row->appendChild($rating);

        $imgTD = $doc->createElement('td');

        //Creating a img tag (use only on)
        $img = $doc->createElement('img');
        $img->setAttribute('src', $r['img_src']);
        $imgTD->appendChild($img);
        $row->appendChild($imgTD);

        $imgTD = $doc->createElement('td');

        //Importing directly from the old document
        $fauxDoc = new DOMDocument();
        $fauxDoc->loadXML($r['img']);
        $img = $fauxDoc->getElementsByTagName('img')->index(0);
        $importedImg = $doc->importNode('$img', true);
        $imgTD->appendChild($importedImg);
        $row->appendChild($imgTD);
    }
    return $doc;
}

function resultsToXML($results)
{
    $doc = new DOMDocumet();
    $root = $doc->createElement('results');
    foreach ($results as $r) {
        $element = $root->createElement('result');
        $element->setAttribute('cover', $r['img_src']);
        $element->setAttribute('title', $r['title']);
        $element->setAttribute('year', $r['year']);
        $element->setAttribute('rating', $r['rating']);
        $root->appendChild($element);
    }
    $doc->appendChild($root);
    return $doc;
}

to print them you just need to

$xml = resultsToXML($results);
print $xml->saveXML();

Same thing with html


Here's a refactor of your code with DOMDocument, based on your post:

<?php
//Mock IMDB Link
$a = 'The Amazing Spider-Man';
$b = 'title';
$c = "http://www.imdb.com/search/title?title=".urlencode($a)."&title_type=".urlencode($b);

// HTML might be malformed so we want DOMDocument to be quiet
libxml_use_internal_errors(true);
//Initialize DOMDocument parser
$doc = new DOMDocument();

//Load previously downloaded document
$doc->loadHTMLFile($c);

//initialize array to store results
$results = array();

// get table of results and extract a list of rows
$listOfTables = $doc->getElementsByTagName('table');
$rows = getResultRows($listOfTables);

$i = 0;
//loop through all rows to retrieve information
foreach ($rows as $row) {
    if ($title = getTitle($row)) {
        $results[$i]['title'] = $title;
    }
    if (!is_null($year = getYear($row)) && $year) {
        $results[$i]['year'] = $year;
    }
    if (!is_null($rating = getRating($row)) && $rating) {
        $results[$i]['rating'] = $rating;
    }
    if ($img = getImage($row)) {
        $results[$i]['img'] = $img;
    }
    if ($src = getImageSrc($row)) {
        $results[$i]['img_src'] = $src;
    }
    ++$i;
}

//the first result can be a false positive due to the
// results' table header, so we remove it
if (isset($results[0])) {
    array_shift($results);
}

FUNCTIONS

function getResultRows($listOfTables)
{
    foreach ($listOfTables as $table) {
        if ($table->getAttribute('class') === 'results') {
            return $table->getElementsByTagName('tr');
        }
    }
}

function getImageSrc($row)
{
    $img = $row->getElementsByTagName('img')->item(0);
    if (!is_null($img)) {
        return $img->getAttribute('src');
    } else {
        return false;
    }
}

function getImage($row, $doc)
{
    $img = $row->getElementsByTagName('img')->item(0);
    if (!is_null($img)) {
        return $doc->saveHTML($img);
    } else {
        return false;
    }
}


function getTitle($row)
{
    $tdInfo = getTDInfo($row->getElementsByTagName('td'));
    if (!is_null($tdInfo) && !is_null($as = $tdInfo->getElementsByTagName('a'))) {
        return $as->item(0)->nodeValue;
    } else {
        return false;
    }
}


function getYear($row)
{
    $tdInfo = getTDInfo($row->getElementsByTagName('td'));
    if (!is_null($tdInfo) && !is_null($spans = $tdInfo->getElementsByTagName('span'))) {
        foreach ($spans as $span) {
            if ($span->getAttribute('class') === 'year_type') {
                return str_replace(')', '', str_replace('(', '', $span->nodeValue));
            }
        }
    }
}

function getRating($row)
{
    $tdInfo = getTDInfo($row->getElementsByTagName('td'));
    if (!is_null($tdInfo) && !is_null($spans = $tdInfo->getElementsByTagName('span'))) {
        foreach ($spans as $span) {
            if ($span->getAttribute('class') === 'rating-rating') {
                return $span->nodeValue;
            }
        }
    }
}


function getTDInfo($tds)
{
    foreach ($tds as $td) {
        if ($td->getAttribute('class') == 'title') {
            return $td;
        }
    }
}

Upvotes: 2

Related Questions