Generated Google Site map not validating - php

I have write this little class below which generates a XML sitemap although when I try to add this to Google Webmaster I get error:
Sitemap URL: http://www.moto-trek.co.uk/sitemap/xml
Unsupported file format
Your Sitemap does not appear to be in a supported format. Please ensure it meets our Sitemap guidelines and resubmit.
<?php
class Frontend_Sitemap_Xml extends Cms_Controller {
/**
* Intercept special function actions and dispatch them.
*/
public function postDispatch() {
$db = Cms_Db_Connections::getInstance()->getConnection();
$oFront = $this->getFrontController();
$oUrl = Cms_Url::getInstance();
$oCore = Cms_Core::getInstance();
$absoDomPath = $oFront->getDomain() . $oFront->getHome();
$pDom = new DOMDocument();
$pXML = $pDom->createElement('xml');
$pXML->setAttribute('version', '1.0');
$pXML->setAttribute('encoding', 'UTF-8');
// Finally we append the attribute to the XML tree using appendChild
$pDom->appendChild($pXML);
$pUrlset = $pDom->createElement('urlset');
$pUrlset->setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
$pXML->appendChild($pUrlset);
// FETCH content and section items
$array = $this->getDataset("sitemap")->toArray();
foreach($array["sitemap"]['rows'] as $row) {
try {
$content_id = $row['id']['fvalue'];
$url = "http://".$absoDomPath.$oUrl->forContent($content_id);
$pUrl = $pDom->createElement('url');
$pLoc = $pDom->createElement('loc', $url);
$pLastmod = $pDom->createElement('lastmod', gmdate('Y-m-d\TH:i:s', strtotime($row['modified']['value'])));
$pChangefreq = $pDom->createElement('changefreq', ($row['changefreq']['fvalue'] != "")?$row['changefreq']['fvalue']:'monthly');
$pPriority = $pDom->createElement('priority', ($row['priority']['fvalue'])?$row['priority']['fvalue']:'0.5');
$pUrl->appendChild($pLoc);
$pUrl->appendChild($pLastmod);
$pUrl->appendChild($pChangefreq);
$pUrl->appendChild($pPriority);
$pUrlset->appendChild($pUrl);
} catch(Exception $e) {
throw($e);
}
}
// Set content type to XML, thus forcing the browser to render is as XML
header('Content-type: text/xml');
// Here we simply dump the XML tree to a string and output it to the browser
// We could use one of the other save methods to save the tree as a HTML string
// XML file or HTML file.
echo $pDom->saveXML();
}
}
?>

urlset should by root element, but in your case it is xml. So appending urlset directly into domdocument should solve your problem.
$pDom = new DOMDocument('1.0','UTF-8');
$pUrlset = $pDom->createElement('urlset');
$pUrlset->setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach( ){ }
$pDom->appendChild($pUrlset);
echo $pDom->saveXML();

Related

Create a WSDL with REST

I have a several problems to moment to create a WSDL with REST in PHP. I read a little bit about this, supposedly REST use WADL. I need a library or framework that generated a WADL or type WSDL of my code PHP (class, methods, vars).
Thanks a lot!
I created a simulation with php but this no get the return vars
... Class
... Methods
... Vars
if(isset($_GET['wadl'])):
header('Content-Type: text/xml');
$foo = new proveedores();
$get_class = get_class($foo);
// create the new XML document
$dom = new DOMDocument('1.0', 'iso-8859-1');
// create the root element
$list_of_teams = $dom->createElement($get_class);
$dom->appendChild($list_of_teams);
$class = new ReflectionClass($get_class);
$methods = $class->getMethods();
foreach ($methods as $m) {
$method = $class->getMethod($m->name);
// create the first element
$team = $dom->createElement($m->name);
$list_of_teams->appendChild($team);
$parameters = $method -> getParameters();
if(!empty($parameters)):
foreach ($parameters as $p) {
$name = $team->appendChild($dom->createElement('parameters'));
$name->appendChild($dom->createTextNode($p -> name));
}
endif;
}
print $xml_result = $dom->saveXML();
endif;

Response of REST API in JSON format

In magento as we use the rest url to access the data, as http://localhost/magento/api/rest/products it returns in xml format instead of that I need JSON.
I have tried below code, but no use
$this->getResponse()->setHeader('Content-type', 'application/json');
$this->getResponse()->setBody($jsonData);
in the folder \magento\app\code\core\Mage\Api\Controller\Action.php
vinox, you should override the default file Request.php. copy \app\code\core\Mage\Api2\Model\Request.php to your local directory and add the following code just before end of the getAcceptTypes() Method.
unset($orderedTypes);
$orderedTypes=Array("application/json" => 1);
in other way your getAcceptTypes() method should look like this.
public function getAcceptTypes(){
$qualityToTypes = array();
$orderedTypes = array();
foreach (preg_split('/,\s*/', $this->getHeader('Accept')) as $definition) {
$typeWithQ = explode(';', $definition);
$mimeType = trim(array_shift($typeWithQ));
// check MIME type validity
if (!preg_match('~^([0-9a-z*+\-]+)(?:/([0-9a-z*+\-\.]+))?$~i', $mimeType)) {
continue;
}
$quality = '1.0'; // default value for quality
if ($typeWithQ) {
$qAndValue = explode('=', $typeWithQ[0]);
if (2 == count($qAndValue)) {
$quality = $qAndValue[1];
}
}
$qualityToTypes[$quality][$mimeType] = true;
}
krsort($qualityToTypes);
foreach ($qualityToTypes as $typeList) {
$orderedTypes += $typeList;
}
unset($orderedTypes);
$orderedTypes=Array("application/json" => 1);
return array_keys($orderedTypes);
}
I guess your $jsonData is not actually JSON. Try using a json helper
$jsonData = Mage::helper('core')->jsonEncode($data)

How do I store mostly static data from a JSON api?

My php project is using the reddit JSON api to grab the title of the current page's submission.
Right now I am doing running some code every time the page is loaded and I'm running in to some problems, even though there is no real API limit.
I would like to store the title of the submission locally somehow. Can you recommend the best way to do this? The site is running on appfog. What would you recommend?
This is my current code:
<?php
/* settings */
$url="http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$reddit_url = 'http://www.reddit.com/api/info.{format}?url='.$url;
$format = 'json'; //use XML if you'd like...JSON FTW!
$title = '';
/* action */
$content = get_url(str_replace('{format}',$format,$reddit_url)); //again, can be xml or json
if($content) {
if($format == 'json') {
$json = json_decode($content,true);
foreach($json['data']['children'] as $child) { // we want all children for this example
$title= $child['data']['title'];
}
}
}
/* output */
/* utility function: go get it! */
function get_url($url) {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,1);
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
?>
Thanks!
Introduction
Here is a modified version of your code
$url = "http://stackoverflow.com/";
$loader = new Loader();
$loader->parse($url);
printf("<h4>New List : %d</h4>", count($loader));
printf("<ul>");
foreach ( $loader as $content ) {
printf("<li>%s</li>", $content['title']);
}
printf("</ul>");
Output
New List : 7New podcast from Joel Spolsky and Jeff Atwood. Good site for example code/ Pyhtonstackoverflow.com has clearly the best Web code ever conceived in the history of the Internet and reddit should better start copying it.A reddit-like, OpenID using website for programmersGreat developer site. Get your questions answered and by someone who knows.Stack Overflow launched into publicStack Overflow, a programming Q & A site. & Reddit could learn a lot from their interface!
Simple Demo
The Problem
I see some things you want to achieve here namely
I would like to store the title of the submission locally somehow
Right now I am doing running some code every time the page is loaded
From what i understand you need is a simple cache copy of your data so that you don't have to load the url all the time.
Simple Solution
A simple cache system you can use is memcache ..
Example A
$url = "http://stackoverflow.com/";
// Start cache
$m = new Memcache();
$m->addserver("localhost");
$cache = $m->get(sha1($url));
if ($cache) {
// Use cache copy
$loader = $cache;
printf("<h2>Cache List: %d</h2>", count($loader));
} else {
// Start a new Loader
$loader = new Loader();
$loader->parse($url);
printf("<h2>New List : %d</h2>", count($loader));
$m->set(sha1($url), $loader);
}
// Oupput all listing
printf("<ul>");
foreach ( $loader as $content ) {
printf("<li>%s</li>", $content['title']);
}
printf("</ul>");
Example B
You can use Last Modification Date as the cache key as so that you would only save new copy only if the document is modified
$headers = get_headers(sprintf("http://www.reddit.com/api/info.json?url=%s",$url), true);
$time = strtotime($headers['Date']); // get last modification date
$cache = $m->get($time);
if ($cache) {
$loader = $cache;
}
Since your class implements JsonSerializable you can json encode your result and also store in a Database like MongoDB or MySQL
$data = json_encode($loader);
// Save to DB
Class Used
class Loader implements IteratorAggregate, Countable, JsonSerializable {
private $request = "http://www.reddit.com/api/info.json?url=%s";
private $data = array();
private $total;
function parse($url) {
$content = json_decode($this->getContent(sprintf($this->request, $url)), true);
$this->data = array_map(function ($v) {
return $v['data'];
}, $content['data']['children']);
$this->total = count($this->data);
}
public function getIterator() {
return new ArrayIterator($this->data);
}
public function count() {
return $this->total;
}
public function getType() {
return $this->type;
}
public function jsonSerialize() {
return $this->data;
}
function getContent($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
}
I'm not sure what your question is exactly but the first thing that pops is the following:
foreach($json['data']['children'] as $child) { // we want all children for this example
$title= $child['data']['title'];
}
Are you sure you want to overwrite $title? In effect, that will only hold the last $child title.
Now, to your question. I assume you're looking for some kind of mechanism to cache the contents of the requested URL so you don't have to re-issue the request every time, am I right? I don't have any experience with appFog, only with orchestra.io but I believe they have the same restrictions regarding writing to files, as in you can only write to temporary files.
My suggestion would be to cache the (processed) response in either:
APC shared memory with a short TTL
temporary files
database
You could use the hash of the URL + arguments as the lookup key, doing this check inside get_url() would mean you wouldn't need to change any other part of your code and it would only take ~3 LOC.
After this:
if($format == 'json') {
$json = json_decode($content,true);
foreach($json['data']['children'] as $child) { // we want all children for this example
$title = $child['data']['title'];
}
}
}`
Then store in a json file and dump it into your localfolder website path
$storeTitle = array('title'=>$title)
$fp = fopen('../pathToJsonFile/title.json'), 'w');
fwrite($fp, json_encode($storeTitle));
fclose($fp);
Then you can always call the json file next time and decode it and extract the title into a variable for use
i usually just store the data as is as a flat file, like so:
<?php
define('TEMP_DIR', 'temp/');
define('TEMP_AGE', 3600);
function getinfo($url) {
$temp = TEMP_DIR . urlencode($url) . '.json';
if(!file_exists($temp) OR time() - filemtime($temp) > TEMP_AGE) {
$info = "http://www.reddit.com/api/info.json?url=$url";
$json = file_get_contents($info);
file_put_contents($temp, $json);
}
else {
$json = file_get_contents($temp);
}
$json = json_decode($json, true);
$titles = array();
foreach($json['data']['children'] as $child) {
$titles[] = $child['data']['title'];
}
return $titles;
}
$test = getinfo('http://imgur.com/');
print_r($test);
PS.
i use file_get_contents to get the json data, you might have your own reasons to use curl.
also i don't check for format, cos clearly you prefer json.

How to create GEXF from PHP?

I need to automatically create GEXF (http://gexf.net) XML files from an array of nodes in PHP.
I've Googled the topic but was unable to find anything useful.
How would I do this?
Here is my take on this. After a number of hours I got it all right. This example has support for the viz: namespace too, so you can use more detailed node elements and placements.
// Construct DOM elements
$xml = new DomDocument('1.0', 'UTF-8');
$xml->formatOutput = true;
$gexf = $xml->createElementNS(null, 'gexf');
$gexf = $xml->appendChild($gexf);
// Assign namespaces for GexF with VIZ :)
$gexf->setAttribute('xmlns:viz', 'http://www.gexf.net/1.1draft/viz'); // Skip if you dont need viz!
$gexf->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$gexf->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation', 'http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd');
// Add Meta data
$meta = $gexf->appendChild($xml->createElement('meta'));
$meta->setAttribute('lastmodifieddate', date('Y-m-d'));
$meta->appendChild($xml->createElement('creator', 'PHP GEXF Generator v0.1'));
$meta->appendChild($xml->createElement('description', 'by me etc'));
// Add Graph data!
$graph = $gexf->appendChild($xml->createElement('graph'));
$nodes = $graph->appendChild($xml->createElement('nodes'));
$edges = $graph->appendChild($xml->createElement('edges'));
// Add Node!
$node = $xml->createElement('node');
$node->setAttribute('id', '1');
$node->setAttribute('label', 'Hello world!');
// Set color for node
$color = $xml->createElement('viz:color');
$color->setAttribute('r', '1');
$color->setAttribute('g', '1');
$color->setAttribute('b', '1');
$node->appendChild($color);
// Set position for node
$position = $xml->createElement('viz:position');
$position->setAttribute('x', '1');
$position->setAttribute('y', '1');
$position->setAttribute('z', '1');
$node->appendChild($position);
// Set size for node
$size = $xml->createElement('viz:size');
$size->setAttribute('value', '1');
$node->appendChild($size);
// Set shape for node
$shape = $xml->createElement('viz:shape');
$shape->setAttribute('value', 'disc');
$node->appendChild($shape);
// Add Edge (assuming there is a node with id 2 as well!)
$edge = $xml->createElement('edge');
$edge->setAttribute('source', '1');
$edge->setAttribute('target', '2');
// Commit node & edge changes to nodes!
$edges->appendChild($edge);
$nodes->appendChild($node);
// Serve file as XML (prompt for download, remove if unnecessary)
header('Content-type: "text/xml"; charset="utf8"');
header('Content-disposition: attachment; filename="internet.gexf"');
// Show results!
echo $xml->saveXML();
Eat your heart out! Feel free to email me your project results, I am curious.

Prevent save() from overwriting dtd in an xml file

I'm writing a script that adds nodes to an xml file. In addition to this I have an external dtd I made to handle the organization to the file. However the script I wrote keeps overwriting the dtd in the empty xml file when it's done appending nodes. How can I stop this from happening?
Code:
<?php
/*Dom vars*/
$dom = new DOMDocument("1.0", "UTF-8");
$previous_value = libxml_use_internal_errors(TRUE);
$dom->load('post.xml');
libxml_clear_errors();
libxml_use_internal_errors($previous_value);
$dom->formatOutput = true;
$entry = $dom->getElementsByTagName('entry');
$date = $dom->getElementsByTagName('date');
$para = $dom->getElementsByTagname('para');
$link = $dom->getElementsByTagName('link');
/* Dem POST vars used by dat Ajax mah ziggen, yeah boi*/
if (isset($_POST['Text'])){
$text = trim($_POST['Text']);
}
/*
function post(){
global $dom, $entry, $date, $para, $link,
$home, $about, $contact, $text;
*/
$entryC = $dom->createElement('entry');
$dateC = $dom->createElement('date', date("m d, y H:i:s")) ;
$entryC->appendChild($dateC);
$tab = "\n";
$frags = explode($tab, $text);
$i = count($frags);
$b = 0;
while($b < $i){
$paraC = $dom->createElement('para', $frags[$b]);
$entryC->appendChild($paraC);
$b++;
}
$linkC = $dom->createElement('link', rand(100000, 999999));
$entryC->appendChild($linkC);
$dom->appendChild($entryC);
$dom->save('post.xml');
/*}
post();
*/echo 1;
?>
It looks like in order to do this, you'd have to create a DOMDocumentType using
DOMImplementation::createDocumentType
then create an empty document using the DOMImplementation, and pass in the DOMDocumentType you just created, then import the document you loaded. This post: http://pointbeing.net/weblog/2009/03/adding-a-doctype-declaration-to-a-domdocument-in-php.html and the comments looked useful.
I'm guessing this is happening because after parsing/validation, the DTD isn't part of the DOM anymore, and PHP therefore isn't able to include it when the document is serialized.
Do you have to use a DTD? XML Schemas can be linked via attributes (and the link is therefore part of the DOM). Or there's RelaxNG, which can be linked via a processing instruction. DTDs have all this baggage that comes with them as a holdover from SGML. There are better alternatives.

Categories