'Display Link Title Instead of URL in XSL

I'm learning XSL-as-I-Go, but I'm stuck.

My function :

public function SitemapHTML()
    {
        
        $xp = new XsltProcessor();
        $xsl = new DomDocument;
        $xsl->load('stylesheet.xsl');

        $xp->importStylesheet($xsl);

        $xml_doc = new DomDocument;
        $xml_doc->load('sitemap.xml');
        $xml_doc->formatOutput = TRUE;

        if ($html = $xp->transformToXml($xml_doc)) {
            echo $html;
        } else {
            return "<p>Il y a eu un problème.</p>";
        }
    }

My XSL :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:stmp="http://www.sitemaps.org/schemas/sitemap/0.9">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTMP Sitemap</title>
</head>
<body>
    <xsl:for-each select="/stmp:urlset/stmp:url/stmp:loc">
    <div>
        <xsl:element name="a">
            <xsl:attribute name="href">
                <xsl:value-of select="."/>
            </xsl:attribute>
                <xsl:value-of select="."/>
        </xsl:element>
    </div>
    </xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

My XML :

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <url>
        <loc>https://www.website.com/</loc>
        <lastmod>2022-03-24T09:25:25+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>
    <url>
        <loc>https://www.website.com/locale/fr</loc>
        <lastmod>2022-03-24T09:25:25+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>

Output :

Output

My question is : In the output, is it possible to display the page's title instead of its URL ? Perhaps I should use a template ? Any help would be appreciated.

EDIT: Whole code, I'm using Laravel :

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\App;
use Spatie\Sitemap\SitemapIndex;
use Spatie\Sitemap\SitemapGenerator;
use Psr\Http\Message\UriInterface;
use DOMDocument;
use XSLTProcessor;

//TODO: Change the homepage priority to 1 in the SitemapXML()
//TODO: Show the page title instead of the URL in the SitemapHTML().


class SitemapController extends Controller
{
    //XML Sitemap Index
    public function SitemapIndex()
    {
        //We add each sitemap to the index, create a new file and redirect to that file
        SitemapIndex::create()
            ->add('/sitemap.xml')
            ->add('/sitemap-activites.xml')
            ->add('/sitemap-villes.xml')
            ->writeToFile('sitemap-index.xml');
            return redirect(url('sitemap-index.xml'));
    }

    //XML Sitemap
    public function SitemapXML()
    {
        //We crawl the entire website then we create a xml sitemap.
        SitemapGenerator::create('https://www.website.com/')

            ->shouldCrawl(function (UriInterface $url) {
                // All pages will be crawled, except for 'activity' and 'metropole'
                return
                    strpos($url->getPath(), '/activity') === false &&
                    strpos($url->getPath(), '/metropole') === false;
            })

            ->writeToFile('sitemap.xml');
            return redirect(url('sitemap.xml'));
    }


    public static function getHtmlTitle($url) {
        $doc = DOMDocument::loadHTMLFile($url);
        return $doc->documentElement->getElementsByTagName('title')->item(0)->textContent;
    }

    //Create a HTML page based on the latest sitemap.xml
    function SitemapHTML()
        {
            $xp = new XsltProcessor();
            $xp->registerPHPFunctions('getHtmlTitle');
            $xsl = new DomDocument;
            $xsl->load('stylesheet.xsl');

            $xp->importStylesheet($xsl);

            $xml_doc = new DomDocument;
            $xml_doc->load('sitemap.xml');
            $xml_doc->formatOutput = TRUE;

            if ($html = $xp->transformToXml($xml_doc)) {
                echo $html;
            } else {
                return "<p>Il y a eu un problème.</p>";
            }
        }

    //XML sitemap for the 'metropolises' DB table
    public function SitemapVilles()
    {
        //Create a sitemap object
        $sitemap = App::make('sitemap');

        //Set homepage URL
        $url = 'http://www.website.com/';

        //Add the homepage URL to the sitemap
        $sitemap->add($url, today(), '1', 'daily');

        //Get all the data from 'metropolises' table
        $metropolises = DB::table('metropolises')->orderBy('created_at', 'asc')->get();

        //Execute a for each loop on the 'metropolises' table and add each entry to the sitemap
        foreach ($metropolises as $metropole) {
            $sitemap->add($url . 'metropole/' . $metropole->name, $metropole->updated_at, '0.64', 'daily');
        }

        //Return the results as an xml file
        $sitemap->store('xml', 'sitemap-villes');

        //Redirect
        return redirect(url('sitemap-villes.xml'));
    }

    //XML sitemap for the 'activities' DB table
    public function SitemapActivites()
    {
        //Create a sitemap object
        $sitemap = App::make('sitemap');

        //Get all the data from 'activities' table
        $activities = DB::table('activities')->orderBy('created_at', 'asc')->get();

        //Set homepage URL
        $url = 'http://www.website.com/';

        //Add the homepage URL to the sitemap
        $sitemap->add($url, today(), '1', 'daily');

        //Execute a for each loop on the 'activities' table and add each entry to the sitemap
        foreach ($activities as $activity) {
            $sitemap->add($url . 'activity/' . $activity->id . '/' . $activity->slug, $activity->updated_at, '0.8', 'daily');
        }

        //Return the results as an xml file
        $sitemap->store('xml', 'sitemap-activites');

        //Redirect
        return redirect(url('sitemap-activites.xml'));
    }
}

Then there's the routes :

//Sitemaps
Route::get('/sitemap-index', [SitemapController::class, 'SitemapIndex'])->name('sitemap-index');
Route::get('/sitemap-html', [SitemapController::class, 'SitemapHTML'])->name('sitemap-html');
Route::get('/sitemap', [SitemapController::class, 'SitemapXML'])->name('sitemap-xml');
Route::get('/sitemap-villes', [SitemapController::class, 'SitemapVilles'])->name('sitemap-villes');
Route::get('/sitemap-activites', [SitemapController::class, 'SitemapActivites'])->name('sitemap-activites');

I'm doing this locally. Therefore, when I visit http://127.0.0.1:8000/sitemap-html, I should have the expected output, but I have this error : Error



Solution 1:[1]

Here is how PHP/XSLT can do it:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:stmp="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:php="http://php.net/xsl" exclude-result-prefixes="php stmp">
<xsl:output method="html" indent="yes" doctype-system="about:legacy-doctype"/>
<xsl:template match="/">
<html>
<head>
<title>Goodtime HTMP Sitemap</title>
</head>
<body>
    <xsl:for-each select="/stmp:urlset/stmp:url/stmp:loc">
    <div>
        <a href="{.}">
          <xsl:value-of select="php:function('getHtmlTitle', string())"/>
        </a>
    </div>
    </xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

PHP

function getHtmlTitle($url) {
    $doc = DOMDocument::loadHTMLFile($url);
    return $doc->documentElement->getElementsByTagName('title')->item(0)->textContent;
}

function SitemapHTML()
    {
        
        $xp = new XsltProcessor();
        $xp->registerPHPFunctions('getHtmlTitle');
        $xsl = new DomDocument;
        $xsl->load('parse-site-map1.xsl');

        $xp->importStylesheet($xsl);

        $xml_doc = new DomDocument;
        $xml_doc->load('sitemap1.xml');
        $xml_doc->formatOutput = TRUE;

        if ($html = $xp->transformToXml($xml_doc)) {
            echo $html;
        } else {
            return "<p>Il y a eu un problème.</p>";
        }
    }

I would hope, however, that you have a local version of both the site map file as well as of all the linked files so that you can read them from your local file system instead of pulling them in over HTTP(S).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1