How to Generate Sitemaps in Memory Without Writing to Disk in PHP
Yes, the msbatal/php-sitemap-generator library constructs XML strings internally before writing them to disk, allowing you to capture sitemaps in memory by extending the SunSitemap class, using PHP reflection, or modifying the source to bypass the fopen and gzopen calls.
The msbatal/php-sitemap-generator repository provides a robust solution for creating XML sitemaps, but by default it always persists files to the server filesystem. By intercepting the generated XML after the asXML() call at line 211 of SunSitemap.php but before the file handles open at lines 240 and 253, you can serve sitemaps dynamically via HTTP, store them in a database, or cache them in memory without requiring write permissions on the disk.
How SunSitemap Handles XML Generation vs. File Writing
The library separates XML construction from persistence. Inside SunSitemap.php, the createSitemap() method first builds each sitemap using SimpleXMLElement and immediately converts it to a string:
// Line 211 - XML exists in memory here
$this->sitemaps[] = $xml->asXML();
Only after populating the private $sitemaps array does the code proceed to disk I/O. It opens the sitemap index file with fopen() at line 240 and individual sitemap files at line 253. When compression is enabled, it switches to gzopen() at lines 245-248. Because the XML strings are already stored in the $sitemaps property, you can extract them before these file operations execute.
Three Approaches to In-Memory Sitemap Generation
Since the XML exists in memory prior to the file-write stage, you can intercept it using one of three techniques.
Extend the Class to Expose Private XML Data
Subclassing SunSitemap provides the cleanest architecture for production use. Override createSitemap() to prevent file writing, then use reflection to expose the private $sitemaps array.
<?php
require_once 'SunSitemap.php';
class InMemorySitemap extends SunSitemap
{
/** Return an array of generated XML strings (one per sitemap file). */
public function getXmlArray(): array
{
$ref = new \ReflectionObject($this);
$prop = $ref->getProperty('sitemaps');
$prop->setAccessible(true);
return $prop->getValue($this);
}
/** Override to skip writing files – we only need the XML. */
public function createSitemap()
{
parent::createSitemap(); // builds XML and fills $sitemaps
// Do NOT call the parent file‑writing code – we stop here.
return $this;
}
}
/* ------------------------------------------------------------------ */
/* Use the subclass */
$sitemap = new InMemorySitemap('https://example.com', null);
$sitemap->addUrl('index.php', date('c'), 'daily', '1');
$sitemap->addUrl('about.php', date('c'), 'weekly', '0.8');
$sitemap->createSitemap(); // builds XML only
$xmlArray = $sitemap->getXmlArray(); // array of XML strings
// Example: send the first sitemap as an HTTP response
header('Content-Type: application/xml');
echo $xmlArray[0]; // the raw XML ready for consumption
This approach preserves the original library's logic while adding a public API for memory-only workflows.
Access Private Properties via Reflection
If you cannot modify the class hierarchy, PHP's reflection API can read the private $sitemaps property at runtime after calling createSitemap().
<?php
require_once 'SunSitemap.php';
$sm = new SunSitemap('https://example.com');
$sm->addUrl('page1.php');
$sm->addUrl('page2.php');
$sm->createSitemap(); // generates XML internally
$ref = new ReflectionObject($sm);
$prop = $ref->getProperty('sitemaps'); // private property
$prop->setAccessible(true);
$xmlArray = $prop->getValue($sm); // array of XML strings
// Output the first sitemap directly
header('Content-Type: application/xml');
echo $xmlArray[0];
Note that this method still executes the fopen and gzopen calls, creating temporary files on disk unless you also patch the source.
Modify the Source to Skip Disk I/O
For a permanent solution that eliminates file creation entirely, edit SunSitemap.php around line 239 and comment out the conditional block containing the fopen and gzopen logic. This leaves the XML generation at line 211 untouched while removing all filesystem operations. After modification, you can retrieve the $sitemaps array via reflection as shown above without creating physical files.
Performance and Architectural Considerations
Generating sitemaps in memory reduces disk I/O overhead and latency, making it ideal for serverless environments, read-only filesystems, or high-traffic applications where sitemaps are served dynamically. However, monitor memory usage when handling large URL sets exceeding PHP's memory_limit, as the entire sitemap collection resides in RAM until the request ends.
Summary
- The
SunSitemapclass inmsbatal/php-sitemap-generatorbuilds XML internally at line 211 before writing to disk at lines 240-253. - The private
$sitemapsarray contains the raw XML strings that you can capture to avoid filesystem operations. - Subclassing provides the cleanest architecture for production applications requiring in-memory sitemaps.
- Reflection offers a quick, non-invasive method for one-off scripts or testing.
- Source modification eliminates I/O overhead entirely but requires maintaining a fork of the library.
Frequently Asked Questions
Does the PHP Sitemap Generator support streaming to memory by default?
No. As implemented in msbatal/php-sitemap-generator, the createSitemap() method always executes fopen() or gzopen() calls to write physical files. The library lacks a native flag to disable disk I/O, necessitating the extension or reflection techniques described above.
Can I generate compressed sitemaps in memory without creating .gz files?
Yes. The library compresses data using gzopen() at lines 245-248, but the underlying XML string exists in memory before compression. You can capture the raw XML from the $sitemaps array and compress it in-memory using gzencode() or store it uncompressed, bypassing the file-based compression workflow entirely.
Will capturing sitemaps in memory work with large datasets?
It depends on your PHP memory_limit configuration. Since the $sitemaps array stores each generated XML string in full, large sitemaps split across multiple files (per the 50,000 URL limit) consume RAM proportional to their total size. For massive datasets, consider implementing a generator pattern or pagination rather than holding all sitemaps in memory simultaneously.
How do I serve an in-memory sitemap as an HTTP response?
After extracting the XML string from the $sitemaps array using either the subclass method or reflection, set the Content-Type: application/xml header and echo the string directly. This approach serves dynamic sitemaps to search engine crawlers without requiring write permissions on the server filesystem.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →