Google Sitemap Xml - Einfach zu Erstellen

Hallo Jungs,

es gibt bestimmt viele unter euch die Ihren Shop bei Google anmelden wollen,
um diesen für Suchmaschinen zu optimieren.

Daher ist aber eine so genannt Google Sitemap Xml von nöten, die leider
bie Oxid nicht dabei ist und auch nur in überteuerten Modulen angeboten wird.

Da wir selber eine schnell Lösung brauchten,
habe ich ein kleines Script aufgesetzt was diese selbst erstellt.

In der Sitemap werden mit SEO URLs alle
Kategorien, Produkte und Kundencmsseiten gespeichert.

[B]google_sitemap_xml.php[/B]


<?php

/*
Google Sitemap Xml v.0.1
--------------------------------
oxid ESales - SEO
--------------------------------
by DIATOM Internet & Medien GmbH
--------------------------------
c: 27.07.2009 | u: 27.07.2009
*/


/* BEGIN - Config ----------------------------------------------------------- */

    // Default
    $xmlList                        = array();
    $xmlInsert                      = array();

    // Config
    $mod_cnf                        = array();
    $mod_cnf['filepath']            = './';
    $mod_cnf['filename']            = 'sitemap.xml';
    $mod_cnf['siteurl']             = 'http://www.domain.de/';
    $mod_cnf['sql_server']          = "localhost";
    $mod_cnf['sql_dbname']          = "";
    $mod_cnf['sql_dbuser']          = "";
    $mod_cnf['sql_dbpw']            = "";
    
    // Error
    $error                          = array();
    $error['connect']               = "keine Mysql Verbindung gefunden!";
    $error['select']                = "kein Mysql Datensatz gefunden!";
    
/* END - Config ------------------------------------------------------------- */


/* BEGIN - Function --------------------------------------------------------- */

    // Function - Create Xml File
    function createXmlFile($xmlInsert) {
    
        global $mod_cnf;
    
        // File Create
        $fp = fopen($mod_cnf['filepath'].$mod_cnf['filename'], "w+");
        fwrite($fp, implode("
", $xmlInsert));
        fclose($fp);  
    }
    
    // Function - get Categorys
    function getCategorys() {
    
        global $mod_cnf;
    
        // Default
        $list       = array();
    
        // Sql - Select
        $sql_sel   = "SELECT
                            oxid,
                            oxtitle,
                            oxdesc,
                            oxlongdesc
                        FROM oxcategories 
                        WHERE
                            oxactive = 1 AND
                            oxhidden = 0
                        ORDER by oxtitle ASC
                        ";
        $sql_query  = mysql_query($sql_sel);
        while( $sql_row = mysql_fetch_array($sql_query) ) {
        
            // Vars
            $loc                = $sql_row['oxid'];
        
            // List
            $list[] = array(
                'loc'           => getSeoUrl($loc),
                'priority'      => '1.0',
                'lastmod'       => date('Y').'-'.date('m').'-'.date('d').'T'.date('h').':'.date('i').':'.date('s').'+00:00',
                'changefreq'    => 'weekly',
            );
        }
        
        return $list;
    }
    
    // Function - get Products
    function getProducts() {
    
        global $mod_cnf;
    
        // Default
        $list       = array();
    
        // Sql - Select
        $sql_sel   = "SELECT
                            oxart.oxid as oxid,
                            oxart.oxartnum as oxartnum,
                            oxart.oxtitle as oxtitle,
                            oxart.oxshortdesc as oxshortdesc,
                            oxart.oxtimestamp as oxtimestamp
                        FROM oxarticles as oxart 
                        LEFT JOIN oxobject2category as oxobj2cat ON ( oxobj2cat.oxobjectid = oxart.oxid )
                        LEFT JOIN oxcategories as oxcat ON ( oxcat.oxid = oxobj2cat.oxcatnid )
                        WHERE
                            oxart.oxactive = 1 AND
                            oxcat.oxactive = 1 AND
                            oxcat.oxhidden = 0
                        ORDER by oxart.oxartnum ASC
                        ";
        $sql_query  = mysql_query($sql_sel);
        while( $sql_row = mysql_fetch_array($sql_query) ) {
        
            // Vars
            $loc                = getSeoUrl($sql_row['oxid']);
            $oxtimestamp        = explode(" ", $sql_row['oxtimestamp']);
        
            // List
            $list[] = array(
                'loc'           => $loc,
                'priority'      => '0.5',
                'lastmod'       => $oxtimestamp[0].'T'.$oxtimestamp[1].'+00:00',
                'changefreq'    => 'daily',
            );
        }
        
        return $list;
    }
    
    // Function - get CMS Sites
    function getCmsSite() {
    
        global $mod_cnf;
    
        // Default
        $list       = array();
    
        // Sql - Select
        $sql_sel   = "SELECT
                            oxid,
                            oxtitle
                        FROM oxcontents
                        WHERE
                            oxactive = 1 AND
                            oxfolder = 'CMSFOLDER_USERINFO'
                        ORDER by oxtitle ASC
                        ";
        $sql_query  = mysql_query($sql_sel);
        while( $sql_row = mysql_fetch_array($sql_query) ) {
        
            // Vars
            $loc                = getSeoUrl($sql_row['oxid']);
        
            // List
            $list[] = array(
                'loc'           => $loc,
                'priority'      => '1.0',
                'lastmod'       => date('Y').'-'.date('m').'-'.date('d').'T'.date('h').':'.date('i').':'.date('s').'+00:00',
                'changefreq'    => 'weekly',
            );
        }
        
        return $list;
    }
    
    // Function - Get SEO URL
    function getSeoUrl($oxid) {
    
        global $mod_cnf;
        
        // Default
        $url        = '';
    
        // Sql - Select
        $sql_sel   = "SELECT
                            oxstdurl,
                            oxseourl
                        FROM oxseo 
                        WHERE
                            oxobjectid = '". $oxid ."' AND
                            oxlang  = '0'
                        LIMIT 1
                        ";
        $sql_query  = mysql_query($sql_sel);
        if( $sql_row = mysql_fetch_array($sql_query) ) {
        
            // Var
            $url = $sql_row['oxseourl'];
            if( empty($url) ) $url = $sql_row['oxstdurl']; 
        
            return $url;
        }
        
        return $url;
    }

/* END - Function ----------------------------------------------------------- */


/* BEGIN - Action ----------------------------------------------------------- */

    // SQL Connect
    $sqlConnect = mysql_connect($mod_cnf['sql_server'], $mod_cnf['sql_dbuser'], $mod_cnf['sql_dbpw']) OR die($error['connect']);
    mysql_select_db($mod_cnf['sql_dbname'], $sqlConnect) OR die($error['select']);

    // Get - Categorys
    $xmlList_cat        = getCategorys();
    
    // Get - Products
    $xmlList_prod       = getProducts();
    
    // Get - Cms Site
    $xmlList_cms        = getCmsSite();
    
    // Output - Xml
    $xmlList            = array_merge($xmlList_cat, $xmlList_prod, $xmlList_cms);


/* END - Action ------------------------------------------------------------- */


/* BEGIN - Output ----------------------------------------------------------- */

    // Vars
    $xmlInsert[] = '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84
	http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">';
    
    foreach($xmlList as $key => $val) {
    
        // Vars
        $xmlInsert[] = '<url>
    <loc>'. $mod_cnf['siteurl'].$val['loc'] .'</loc>
    <priority>'. $val['priority'] .'</priority>
    <lastmod>'. $val['lastmod'] .'</lastmod>
    <changefreq>'. $val['changefreq'] .'</changefreq>
</url>';
    }
    
    // Vars
    $xmlInsert[] = '</urlset>';
    
    
    // Create Xml File
    createXmlFile($xmlInsert);
    
    
    // Output - User Info
    echo '<a href="'. $mod_cnf['filepath'].$mod_cnf['filename'] .'" target="_blank">XML Datei betrachten</a>';

/* END - Output ------------------------------------------------------------- */

?>

Später soll sich das ganze noch automatisch aktualisieren und
auch mehrere Sprachen unterstützen.

mfg, Sebastian

P.s. more Modules 4 Free :wink:

Hallo Sebastian,

erstmal Danke für Deine Arbeit. Wo allerdings lege ich diese Datei ab ?

Sonnige Grüße aus Dresden

Dirk

Einfach im Hauptordner von Oxid, würde ich sagen.
Ist aber ehh egal, weil die Datei ohne Oxid arbeitet.

Also SQL Daten net vergessen :wink: ( siehe $mod_cnf )

grüße, Sebastian

Danke Sebastian.

Dirk

super Sache !

Vielen Dank.

Aber ich habe da noch ein Problem:
Ich habe meine Artikel teilweise in 2 Kategorien stehen. Die URL bleibt dieselbe. Nun wird diese URL 2 mal eingetragen.
Habe nun für die Funktion get Products statt
Select
nun
select distinct
eingefügt. Scheint meiner Meinung nach zu funktionieren.
Da ich aber nun mal keine Ahnung habe, frage ich lieber:
Bekomme ich nun andere Probleme (URLs, die er mir nun zuwenig ausgibt oder ähnliches)?
Und wenn ja, wie kann ich es besser machen?

Danke
Michael

Ohh, daran hab ich gar nicht gedacht.

Folgende Lösung sollte das Problem lösen:

[B]Function: (Änderung)[/B]


// Function - get Products
    function getProducts() {
    
        global $mod_cnf;
    
        // Default
        $list       = array();
    
        // Sql - Select
        $sql_sel   = "SELECT
                            oxart.oxid as oxid,
                            oxart.oxartnum as oxartnum,
                            oxart.oxtitle as oxtitle,
                            oxart.oxshortdesc as oxshortdesc,
                            oxart.oxtimestamp as oxtimestamp
                        FROM oxarticles as oxart 
                        LEFT JOIN oxobject2category as oxobj2cat ON ( oxobj2cat.oxobjectid = oxart.oxid )
                        LEFT JOIN oxcategories as oxcat ON ( oxcat.oxid = oxobj2cat.oxcatnid )
                        WHERE
                            oxart.oxactive = 1 AND
                            oxcat.oxactive = 1 AND
                            oxcat.oxhidden = 0
                        GROUP by oxart.oxid
                        ORDER by oxart.oxartnum ASC
                        ";
        $sql_query  = mysql_query($sql_sel);
        while( $sql_row = mysql_fetch_array($sql_query) ) {
        
            // Vars
            $loc                = getSeoUrl($sql_row['oxid']);
            $oxtimestamp        = explode(" ", $sql_row['oxtimestamp']);
        
            // List
            $list[] = array(
                'loc'           => $loc,
                'priority'      => '0.5',
                'lastmod'       => $oxtimestamp[0].'T'.$oxtimestamp[1].'+00:00',
                'changefreq'    => 'daily',
            );
        }
        
        return $list;
    }

  • “GROUP by oxart.oxid”
  • Jetzt sollte sich die SQL Abfrage nur auf die Tabelle “oxarticles” beziehen
    und doppelte Einträge im “Left Join” ignorieren.

Sonst sollte alles normal funktionieren.

P.s. Getestet habe ich es noch nicht ^^

mfg, Sebastian

Hallo Sebastian
Danke, sieht gut aus (ich habe zumindest nun keine Doppelten mehr).

Für die Produktsuche habe ich aber als Kriterium noch:
oxart.oxstock > 0
eingefügt.
Artikel, die ich nicht mehr auf Lager habe, werden bei mir nicht gelistet. Habe ich also für die Sitemap dann auch herrausgenommen.
Gruss
Michael

[QUOTE=DIATOM;11311]
Später soll sich das ganze noch automatisch aktualisieren und
[/QUOTE]

Habe leider keine Zeit das zu testen, aber mit CSS-Dateien klappt folgende Vorgehnsweise recht gut.

.htaccess (Apache muss solch eine Regel erlauben… )


# *.xml soll als php ausgeführt werden...
AddType application/x-httpd-php5 .php .xml
# oder (je nach Server)
# AddType application/x-httpd-php .php .xml

Dann die sitemap.php Datei so umbennen, dass diese halt sitemap.xml heißt… XML wird ja nun als PHP ausgeführt.

Ganz am Anfang der ‘php-Datei’ (nun ja xml-Datei)

header('Content-type: text/xml');

schreiben.
Weiterhin dies Modul so ändern, dass keine Datei erzeugt wird, sondern einfach der xml-String als Text ausgegeben wird.

So sollte sobald die sitemap.xml aufgerufen wird, die aktuelle Sitemap angezeigt werden.

Das ist an sich eine super Idee.
Die ich am Anfang auch schon hatte.

Aber ich finde die Lösung zu Speicherintensiv.
Da bei jedem Aufruf die Datenbank belastet wird und
das kann bei mehrfacher Verwendung auf verschieden Webseiten,
schnell viele Anfragen werden. ( Rein Theoretisch ^^ )

Daher finde ich die Erstellung einer eigenständigen Xml Datei besser.
Diese kann unbegrenzt abgerufen werden, ohne auf die Performance zu schlagen.

Für die automatische Aktualisierung wäre z.b. ein Cronjob, ein Shell Script
oder ein Php Script ganz gut. Das die Xml Php 1 mal am Tag ausführt.

Da sich in einem Shop eh nur 1 mal am Tag was ändert und nur selten stündlich.

mfg, Sebastian

Hallo,

ich bekomme folgenden Fehler angezeigt wenn ich die xml Datei mir anschauen will. :-S

Parse error: syntax error, unexpected T_STRING in /var/www/oxid/sitemap.xml on line 1

Hilfe…

[QUOTE=haneb187;11532]Hallo,

ich bekomme folgenden Fehler angezeigt wenn ich die xml Datei mir anschauen will. :-S

Parse error: syntax error, unexpected T_STRING in /var/www/oxid/sitemap.xml on line 1

Hilfe…[/QUOTE]

Vielleicht die SQL Zugänge nicht eingeben ?

Siehe “$mod_cnf” im Header der php

mfg, Sebastian

Bei mir klappt alles wenn ich es manuell ausführe und damit kann ich leben.
Danke nochmals. :slight_smile:

Nur mit dem Cronjob will es noch nicht so richtig.
Felhermeldung:

/google_sitemap_xml.php: Permission denied

Da ich das File im Hauptverzeichnis liegen habe will ich aber dort keine Zurgriffsrechte ändern. Ich muß mal gucken ob man das sitemap.xml File ins Hauptvezeichniss geschrieben bekommt und die google_sitemap_xml.php dann in irgend ein Unterverzeichniss packen kann.

Oder hast du dafür eine schnelle Lösung ?

Noch eine Frage: Pro Artikel will ich nur eine Zeile haben, damit ich schneller einen Überblick über die aufgenommenen Zeilen erhalte. Erreich ich dies, wenn ich nach “Begin Output” (2. Absatz) alles in eine Zeile schreibe, also die Zeilenumbrüche entferne ?

CYA
Firefax

[QUOTE=Firefax;11567]Bei mir klappt alles wenn ich es manuell ausführe und damit kann ich leben.
[B]Danke nochmals.[/B] :slight_smile:

Nur mit dem Cronjob will es noch nicht so richtig.
Felhermeldung:

Da ich das File im Hauptverzeichnis liegen habe will ich aber dort keine Zurgriffsrechte ändern. Ich muß mal gucken ob man das sitemap.xml File ins Hauptvezeichniss geschrieben bekommt und die google_sitemap_xml.php dann in irgend ein Unterverzeichniss packen kann.

Oder hast du dafür eine schnelle Lösung ?

Noch eine Frage: Pro Artikel will ich nur eine Zeile haben, damit ich schneller einen Überblick über die aufgenommenen Zeilen erhalte. Erreich ich dies, wenn ich nach “Begin Output” (2. Absatz) alles in eine Zeile schreibe, also die Zeilenumbrüche entferne ?

CYA
Firefax[/QUOTE]

Huhu,

bei einem “Cronjob / Crontab” lässt sich das Script entweder
über den Root-Pfad oder den Url-Pfad ausführen.
Bei Linux Systemen geht es nur über ein Zusatztool.

http://www.good-tutorials.de/Linux/Administration/CronJobs-unter-Linux-einrichten-141.html

Vielleicht die “google_sitemap_xml.php” in ein extra Verzeichnis verschieben und
diese mit einer subdomain koppeln und die mit dem cronjob ausführen.

Deine letzte Frage verstehe ich nicht,
hat die was mit der Sitemap zu tun ??
Bitte etwas genauer erläutern.

mfg, Sebastian

Hi
In der Shopsoftware, die ich vor Oxid eingesetzt hatte, habe ich eine Sitemap gehabt, die sich bei jedem Aufruf selbst generiert (Danke an den User Eisbehr!).

Nach der Vorlage von Sebastian, habe ich dies mit dieser Datei auch umgesetzt.
Aber wie immer, vor Einsatz bitte Dateien sichern!!!

Also man nehme die Datei google_sitemap_xml.php von Sebastian, und lösche gleich hinter /* BEGIN - Function die Zeilen:

// Function - Create Xml File
function createXmlFile($xmlInsert) {

    global $mod_cnf;

    // File Create
    $fp = fopen($mod_cnf['filepath'].$mod_cnf['filename'], "w+");
    fwrite($fp, implode("

", $xmlInsert));
fclose($fp);
}

Und zwischen Begin Output und End Output löscht man die Zeilen und setzt folgende ein:

if($_GET[‘mode’] == ‘xml’) header(“Content-type: text/xml”);
if($_GET[‘mode’] == ‘txt’) header(“Content-type: text/plain”);

if($_GET[‘mode’] == ‘xml’)

{
echo “<?xml version=“1.0” encoding=“UTF-8”?>
”;
echo “<urlset
”;
echo " xmlns=“http://www.google.com/schemas/sitemap/0.84"
”;
echo " xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance
";
echo " xsi:schemaLocation=“http://www.google.com/schemas/sitemap/0.84
”;
echo " http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">
";

if($_GET[‘mode’] == ‘xml’)
// Vars

$xmlInsert[] = '&lt;?xml version="1.0" encoding="UTF-8"?&gt;

<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.google.com/schemas/sitemap/0.84
http://www.google.com/schemas/sitemap/0.84/sitemap.xsd”>’;

foreach($xmlList as $key =&gt; $val) {

    // Vars


    echo "&lt;url&gt;

“;
echo " <loc>” . $mod_cnf[‘siteurl’].$val[‘loc’] . “</loc>
”;
echo " <priority>" . $val[‘priority’] . “</priority>
”;
echo " <lastmod>" . $val[‘lastmod’] . “</lastmod>
”;
echo " <changefreq>" . $val[‘changefreq’] . “</changefreq>
”;
echo “</url>
”;
}
}

if($_GET[‘mode’] == ‘txt’)
foreach($xmlList as $key => $val) {
{
echo $mod_cnf[‘siteurl’].$val[‘loc’] . “
”;
}
}

if($_GET[‘mode’] == ‘xml’) echo “</urlset>”;

Datei Abspeichern und ins Hauptverzeichnis laden.

In der .htaccess kommen dann noch folgende Einträge:
RewriteRule ^urllist.txt$ google_sitemap_xml.php?mode=txt
RewriteRule ^sitemap.txt$ google_sitemap_xml.php?mode=txt
RewriteRule ^sitemap.xml$ google_sitemap_xml.php?mode=xml

Das war’s (wenn ich nichts vergessen habe!?).

Es wird hier auch eine Textdatei generiert. Ich habe keine Ahnung, ob yahoo wirklich noch die urllist.txt brauch, habe da Unterschiedliche Berichte gelesen. Wenn man die Textdatei nicht haben will, muss man sich die halt wieder rausschmeißen.

Keine Ahnung, ab wieviel Artikel/Varianten diese Methode nicht mehr zu empfehlen ist. Ich habe ca. 500 Artikel, und damit geht es recht zügig.
Gruss
Michael

Von einer Yahoo Seite:

Welche Feeds werden unterstützt?
Feeds werden in den nachfolgenden Formaten akzeptiert. Komprimierte Dateien mit der Endung .gz werden erkannt und vor dem parsen entpackt.

* RSS 0.9, RSS 1.0, oder RSS 2.0 (siehe RSS Feeds)
* Sitemaps (siehe www.sitemaps.org)
* Atom 0.3 oder Atom 1.0
* Eine Text-Datei, die URLs enthält. Jede URL muss in einer neuen Zeile stehen. Der Dateiname muss urllist.txt lauten. Bei einer komprimierten Datei lautet der Dateiname urllist.txt.gz.

Ich habe meine Sitemap bei Yahoo mal angegeben, bisher noch keine Reaktion. Mal abwarten.

@ DIATOM
Das “Permission denied” war ja das Ergebnis meines über die Weboberfläche meines Webhosters angeleten Cronjobs. Der Cronjob an sich geht. Er scheint nur im Hauptverzeichnis nicht die nötigen Rechte zu besitzen.

Daher war die Frage ob man es nicht so Programmieren kann, dass man sagen kann wohin der Output, also sitemap.xml geschrieben werden soll. Im Moment liegt die doch dann immer in demselben Verzeichniss wie die ausgeführte Datei.

edit Habe nochmal darüber nachgedacht, so wie ich das wollte gehts wahrscheinlich nicht. Ich probiere es ggf. mal wie du Vorgeschlagen hast mit Subdomains und Unterverzeichnissen. /edit

Meine letzte Frage bezog sich auf die Ausgabe in der sitemap. Du verwendest 6 Zeilen für <url> <loc>http://www…html</loc> <priority>0.5</priority> <lastmod>2009-07-26T08:00:17+00:00</lastmod> <changefreq>daily</changefreq> </url>
Ich habe mal die Zeilenumbrüche entfernt und nun steht alles in einer Zeile. Darurch habe ich als User einen besseren Überblick, wenn ich mal in die Sitemap reingucke. (Ok aus Sicht eines Proggramierers sicherlich grausam :wink:
Meine Frage hat sich somit erledigt.

CYA
Firefax

Ein Problem habe ich noch:
Für die Kategorien erhalte ich jeweils nur eine URL.
Teilweise habe ich aber 10 Seiten und mehr.
Die Url, die er mir aber nun aussucht, ist irgendeine der Seiten, also z.B.:
http://www.meinedomain.de/Kategorie/2/

Wie bekomme ich alle angezeigt?
Danke

Hallo Sebastian (und die Anderen),

ich verstehe leider zu wenig von Programmierung, um wirklich folgen zu können - dennoch interessiert mich das Thema.

Wäre es denn möglich, nochmal das optimierte Script hier reinzustellen - mit ein paar Stichworten für einen Neulinng, wie man es handhabt?

Herzlichen Dank schonmal für Eure Mühe
Angela

grandios DIATOM, das läuft perfekt. Thx

Hallo DIATOM,

bekommt ihr das auch für die 3er Version hin?

best wüsches
oberleiner