parsing and comparing xml values using PHP XML DOM - php

I am trying to compare a node value and parse xml attribute values using PHP's DOM XML.
Below is what I have on my page but I am no longer get the results or an error.
PHP:
<?PHP
error_reporting(E_ALL);
ini_set("display_errors", 1);
//PRODUCT URL
$xml_url = "http://<servername>/services/info?storeId=2;
//LOCAL TEST URL
//$xml_url = "testXML.xml";
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml_url);
//THIS IS WHERE MY ISSUE IS (I THINK)
$errorCheck = $xmlDoc->getElementsByTagName( "testcode"" );
$errorValue = $errorCheck->item(0)->nodeValue;
if ($errorValue != "1"){
//loop and show data
$grads = $xmlDoc->getElementsByTagName( "$grads" );
foreach( $grads as $grad )
{
$students = $grad->getElementsByTagName( "student" );
$student = $students>item(0)->nodeValue;
$times = $grad->getElementsByTagName( "time" );
$time = $times->item(0)->nodeValue;
echo "<tr><td>".$student."</td><td>".$time."</td></tr>";
}
}else{
?>
<H1> Show an html message</H1>
<?
}
?>
THIS IS MY TEST XML:
<response>
<testcode>0</testcode>
<grad student="mike" time="10:00am"/>
<grad student="Bob" time="11:00am" />
<grad student="TOM" time="11:30am" />
<grad student="Greg" time="1:00pm" />
</response>

Related

I am trying to scrap website but get only one array detail in xml file

I am trying to scrape this webpage. In this webpage I have to get the job title and its location. Which I am able to get from my code. But the problem is coming that when I am sending it in XML, then only one detail is going from the array list.
I am using goutte CSS selector library and also please tell me how to scrap pagination in goutte CSS selector library.
here is my code:
$httpClient = new \Goutte\Client();
$response = $httpClient->request('GET', 'https://www.simplyhired.com/search?q=pharmacy+technician&l=American+Canyon%2C+CA&job=X5clbvspTaqzIHlgOPNXJARu8o4ejpaOtgTprLm2CpPuoeOFjioGdQ');
$job_posting_location = [];
$response->filter('.LeftPane article .SerpJob-jobCard.card .jobposting-subtitle span.JobPosting-labelWithIcon.jobposting-location span.jobposting-location')
->each(function ($node) use (&$job_posting_location) {
$job_posting_location[] = $node->text() . PHP_EOL;
});
$joblocation = 0;
$response->filter('.LeftPane article .SerpJob-jobCard.card .jobposting-title-container h3 a')
->each( function ($node) use ($job_posting_location, &$joblocation, $httpClient) {
$job_title = $node->text() . PHP_EOL; //job title
$job_posting_location = $job_posting_location[$joblocation]; //job posting location
// display the result
$items = "{$job_title} # {$job_posting_location}\n\n";
global $results;
$result = explode('#', $items);
$results['job_title'] = $result[0];
$results['job_posting_location'] = $result[1];
$joblocation++;
});
function convertToXML($results, &$xml_user_info){
foreach($results as $key => $value){
if(is_array($value)){
$subnode = $xml_user_info->addChild($key);
foreach ($value as $k=>$v) {
$xml_user_info->addChild("$k",htmlspecialchars("$v"));
}
}else{
$xml_user_info->addChild("$key",htmlspecialchars("$value"));
}
}
return $xml_user_info->asXML();
}
$xml_user_info = new SimpleXMLElement('<root/>');
$xml_content = convertToXML($results,$xml_user_info);
$xmlFile = 'details.xml';
$handle = fopen($xmlFile, 'w') or die('Unable to open the file: '.$xmlFile);
if(fwrite($handle, $xml_content)) {
echo 'Successfully written to an XML file.';
}
else{
echo 'Error in file generating';
}
what i got in xml file --
<?xml version="1.0"?>
<root><job_title>Pharmacy Technician
</job_title><job_posting_location> Vallejo, CA
</job_posting_location></root>
what i want in xml file --
<?xml version="1.0"?>
<root>
<job_title>Pharmacy Technician</job_title>
<job_posting_location> Vallejo, CA</job_posting_location>
<job_title>Pharmacy Technician 1</job_title>
<job_posting_location> Vallejo, CA</job_posting_location>
<job_title>Pharmacy Technician New</job_title>
<job_posting_location> Vallejo, CA</job_posting_location>
and so on...
</root>
You overwrite the values in the $results variable. You're would need to do something like this to append:
$results[] = [
'job_title' => $result[0];
'job_posting_location' => $result[1]
];
However here is no need to put the data into an array at all, just create the
XML directly with DOM.
Both your selectors share the same start. Iterate the card and then fetch
related data.
$httpClient = new \Goutte\Client();
$response = $httpClient->request('GET', $url);
$document = new DOMDocument();
// append document element node
$postings = $document->appendChild($document->createElement('jobs'));
// iterate job posting cards
$response->filter('.LeftPane article .SerpJob-jobCard.card')->each(
function($jobCard) use ($document, $postings) {
// fetch data
$location = $jobCard
->filter(
'.jobposting-subtitle span.JobPosting-labelWithIcon.jobposting-location span.jobposting-location'
)
->text();
$title = $jobCard->filter('.jobposting-title-container h3 a')->text();
// append 'job' node to group data in result
$job = $postings->appendChild($document->createElement('job'));
// append data nodes
$job->appendChild($document->createElement('job_title'))->textContent = $title;
$job->appendChild($document->createElement('job_posting_location'))->textContent = $location;
}
);
echo $document->saveXML();

PHP DOMDocument: Get attribute value from id

I would like to extract the value of the attribute "value" using the id tag.
My code:
<?php
$url = 'http://turni.tt-contact.com/Default.aspx';
$contents = htmlentities(file_get_contents($url));
echo $contents."\n"; //html
$dom = new DOMDocument;
$dom->validateOnParse = true;
$dom->loadHTML($contents);
$dom->preserveWhiteSpace = false;
$data = $dom->getElementById("__VIEWSTATE");
echo $data->nodeValue;
?>
I would like the attribute "value" -> "THIS":
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="THIS">
but the code returns only the html code.
What do I need to change?
Also by modifying it to:
$xpath = new DOMXpath($dom);
$data = $xpath->query('//input[#id="__VIEWSTATE"]');
$node = $data->item(0);
echo $node->getAttribute('value');
I get this error:
Fatal error: Call to a member function getAttribute() on null
Try this :
$data->getAttribute('value');
PHP: DomElement->getAttribute
$attrs = array();
for ($i = 0; $i < $data->attributes->length; ++$i){
$node = $data->attributes->item($i);
$attrs[$node->nodeName] = $node->nodeValue;
}
var_dump($attrs);
Don't use htmlentities as it will change the document's HTML tags from : <html> to <html>and your document won't be HTML anymore, just a plain text full of < and >, and so the methods to get nodes won't work.

getting the element from the p tag

How can I get the content from the <p> tag inside a p tag with ID categories using DOMDocument?
Here is the code:
<?php
ini_set('max_execution_time', 300);
//error_reporting(0);
$errmsg_arr = array();
$errflag = false;
function getState($string)
{
$ex = explode(" ",$string." ");
return $ex[1];
}
$xml = "";
$xml .= '<?xml version="1.0" encoding="UTF-8" ?>';
$xml .= '
<tv generator-info-name="www.mysite.com/xmltv">';
$baseUrl = file_get_contents('www.myscript.com/get-listing.php');
$domdoc = new DOMDocument();
$domdoc->strictErrorChecking = false;
$domdoc->recover=true;
$domdoc->loadHTML($baseUrl);
?>
For example, my HTML might look like:
<p id='categories'>Sports</p>
I'm trying to extract the following text:
Sports
So when I tried this:
$p = $domdoc->getElementById('categories')->getElementsByTagName('p')->item(0);
echo $p;
It will not extract the content from the id categories.
How can I do it?
For that html only, you can do it like this:
echo $domdoc->getElementById('categories')->nodeValue;
Output:
Sports
See it in action here.
Since you can't have a <p> tag inside <p> tag, DOMDocument kind goes crazy about it. Depending on the case, you could do a workaround like this:
$baseUrl = '
<p id="categories">
<p>Sports</p>
</p>';
$baseUrl = str_replace('<p', '<div', $baseUrl);
$baseUrl = str_replace('<p>', '<div>', $baseUrl);
$baseUrl = str_replace('</p>', '</div>', $baseUrl);
$domdoc = new DOMDocument();
$domdoc->loadHTML($baseUrl);
echo $domdoc->getElementById('categories')->getElementsByTagName('div')->item(0)->nodeValue;
The output is the same as before.

viewing XML data if attribute value equals variable value

I'm stuck on something extremely simple.
Here is my xml feed:
http://xml.betfred.com/Horse-Racing-Daily.xml
Here is my code
<?php
function HRList5($viewbets) {
$xmlData = 'http://xml.betfred.com/Horse-Racing-Daily.xml';
$xml = simplexml_load_file($xmlData);
$curdate = date('d/m/Y');
$new_array = array();
foreach ($xml->event as $event) {
if($event->bettype->attributes()->bettypeid == $viewbets){//$_GET['evid']){
// $eventid = $_GET['eventid'];
// if ($limit == $c) {
// break;
// }
// $c++;
$eventd = substr($event->attributes()->{'date'},6,2);
$eventm = substr($event->attributes()->{'date'},4,2);
$eventy = substr($event->attributes()->{'date'},0,4);
$eventt = $event->attributes()->{'time'};
$eventid = $event->attributes()->{'eventid'};
$betname = $event->bettype->bet->attributes()->{'name'};
$bettypeid = $event->bettype->attributes()->{'bettypeid'};
$betprice = $event->bettype->bet->attributes()->{'price'};
$betid = $event->bettype->bet->attributes()->{'id'};
$new_array[$betname.$betid] = array(
'betname' => $betname,
'viewbets' => $viewbets,
'betid' => $betid,
'betname' => $betname,
'betprice' => $betprice,
'betpriceid' => $event->bettype->attributes()->{'betid'},
);
}
ksort($new_array);
$limit = 10;
$c = 0;
foreach ($new_array as $event_time => $event_data) {
// $racedate = $event_data['eventy'].$event_data['eventm'].$event_data['eventd'];
$today = date('Ymd');
//if($today == $racedate){
// if ($limit == $c) {
// break;
//}
//$c++;
$replace = array("/"," ");
// $eventname = str_replace($replace,'-', $event_data['eventname']);
//$venue = str_replace($replace,'-', $event_data['venue']);
echo "<div class=\"units-row unit-100\">
<div class=\"unit-20\" style=\"margin-left:0px;\">
".$event_data['betprice']."
</div>
<div class=\"unit-50\">
".$event_data['betname'].' - '.$event_data['betprice']."
</div>
<div class=\"unit-20\">
<img src=\"betnow.gif\" ><br />
</div>
</div>";
}
}//echo "<strong>View ALL Horse Races</strong> <strong>>></strong>";
//var_dump($event_data);
}
?>
Now basically the XML file contains a list of horse races that are happening today.
The page I call the function on also declares
<?php $viewbets = $_GET['EVID'];?>
Then where the function is called I have
<?php HRList5($viewbets);?>
I've just had a play around and now it displays the data in the first <bet> node
but the issue is it's not displaying them ALL, its just repeating the 1st one down the page.
I basically need the xml feed queried & if the event->bettype->attributes()->{'bettypeid'} == $viewbets I want the bet nodes repeated down the page.
I don't use simplexml so can offer no guidance with that - I would say however that to find the elements and attributes you need within the xml feed that you ought to use an XPath query. The following code will hopefully be of use in that respect, it probably has an easy translation into simplexml methods.
Edit: Rather than targeting each bet as the original xpath did which then caused issues, the following should be more useful. It targets the bettype and then processes the childnodes.
/* The `eid` to search for in the DOM document */
$eid=25573360.20;
/* create the DOM object & load the xml */
$dom=new DOMDocument;
$dom->load( 'http://xml.betfred.com/Horse-Racing-Daily.xml' );
/* Create a new XPath object */
$xp=new DOMXPath( $dom );
/* Search the DOM for nodes with particular attribute - bettypeid - use number function from XSLT to test */
$oCol=$xp->query('//event/bettype[ number( #bettypeid )="'.$eid.'" ]');
/* If the query was successful there should be a nodelist object to work with */
if( $oCol ){
foreach( $oCol as $node ) {
echo '
<h1>'.$node->parentNode->getAttribute('name').'</h1>
<h2>'.date('D, j F, Y',strtotime($node->getAttribute('bet-start-date'))).'</h2>';
foreach( $node->childNodes as $bet ){
echo "<div>Name: {$bet->getAttribute('name')} ID: {$bet->getAttribute('id')} Price: {$bet->getAttribute('price')}</div>";
}
}
} else {
echo 'XPath query failed';
}
$dom = $xp = $col = null;

Convert form request data to xml in cakephp

I'm trying to convert all the form data in a cakephp request object to xml and then convert that to a string so that I can place it in a (blob) column in a mysql table.
I'm trying to do this current using the buildin xml builders in CakePHP 2.x.x as shown below but am getting an error.
if ($this->request->is('post')) {
$this->Survey->create();
$xml = Xml::build($this->request->data);
}
The form is shown below
<?php echo $this->Form->create('Survey'); ?>
<fieldset>
<legend><?php echo __('Add Survey'); ?></legend>
<?php
echo $this->Form->input('Question 1');
echo $this->Form->input('Question 2');
echo $this->Form->input('Question 3');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
The error I'm getting seems to be due to the DOCDocument->createElement(string,string) in the stacktrace. I've also used other methods including building it manually like so:
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$doc->loadHTML($this->request->data);
$data = $this->request->input('Xml::build',
array('return' => 'domdocument'));
while(list($key,$value) = each($this->request->data)){
$data = $data . $key . $value;
}
if(isset($this->request->data)){
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$root = $doc->appendChild($doc->createElement('survey'));
$post = $this->request->data['Survey'];
unset($post['submit']);
foreach($post as $key => $value){
$node = $doc->createElement($key,$value);
$root->appendChild($node);
}
$test1 = $doc->saveXML();
Any help would be appreciated. Thank you.
See the transforming an array into a string of XML section.

Categories