Skip to main content

Overview

View exports allow you to generate XML using Laravel Blade templates. This approach gives you the full power of Blade’s templating engine - loops, conditionals, components, and more - while generating well-formed XML documents. View exports are ideal for:
  • Complex XML structures with conditional elements
  • Reusing existing Blade templates
  • XML with dynamic content that changes based on data
  • Large XML files where array syntax becomes unwieldy

Basic view export

Create a Blade view file with XML markup, then export it using the XML::exportView() method:

Create the Blade view

Create a file at resources/views/files.blade.php:
@foreach($files as $file)
    <file>
        <name>{{ $file['name'] }}</name>
        <type>{{ $file['type'] }}</type>
    </file>
@endforeach

Export the view

use Flowgistics\XML\XML;

$data = [
    'files' => [
        ['name' => 'file1', 'type' => 'pdf'],
        ['name' => 'file2', 'type' => 'png'],
        ['name' => 'file3', 'type' => 'xml'],
    ],
];

$xml = XML::exportView('files', $data)
    ->setRootTag('files')
    ->version('1.0')
    ->encoding('UTF-8')
    ->toString();

Generated output

<?xml version="1.0" encoding="UTF-8"?>
<files>
    <file>
        <name>file1</name>
        <type>pdf</type>
    </file>
    <file>
        <name>file2</name>
        <type>png</type>
    </file>
    <file>
        <name>file3</name>
        <type>xml</type>
    </file>
</files>

View exports without root tag

If your Blade view already includes a root element, you can disable the automatic root tag wrapper:

Blade view with root element

<files>
    @foreach($files as $file)
        <file>
            <name>{{ $file['name'] }}</name>
            <type>{{ $file['type'] }}</type>
        </file>
    @endforeach
</files>

Export without root tag

$xml = XML::exportView('no-root', $data)
    ->disableRootTag()
    ->toString();
Use disableRootTag() when your Blade template manages its own root element structure.

Exporting to files

Save the generated XML directly to a file:
XML::exportView('files', $data)
    ->setRootTag('files')
    ->version('1.0')
    ->encoding('UTF-8')
    ->toFile('output/files.xml');
The toFile() method uses Laravel’s File facade, which automatically creates parent directories if they don’t exist.

Configuration options

View exports support all the standard XML builder configuration:
XML::exportView('products', $data)
    ->setRootTag('catalog')           // Set custom root tag
    ->version('1.0')                  // XML version
    ->encoding('UTF-8')               // Character encoding
    ->toString();

Available methods

setRootTag
string|false
Set the root element name. Pass false or use disableRootTag() to disable.
disableRootTag
void
Disable the automatic root element wrapper.
version
string
default:"1.0"
Set the XML version in the prolog.
encoding
string
default:"UTF-8"
Set the character encoding in the prolog.
toString
string
Return the XML as a string.
toFile
void
Save the XML to a file at the specified path.

Advanced Blade techniques

Conditional elements

Use Blade conditionals to include elements only when certain conditions are met:
<products>
    @foreach($products as $product)
        <product>
            <name>{{ $product['name'] }}</name>
            <price>{{ $product['price'] }}</price>
            
            @if(isset($product['sale_price']))
                <sale_price>{{ $product['sale_price'] }}</sale_price>
            @endif
            
            @if($product['in_stock'])
                <availability>In Stock</availability>
            @else
                <availability>Out of Stock</availability>
            @endif
        </product>
    @endforeach
</products>

Nested loops

Generate complex nested XML structures:
<catalog>
    @foreach($categories as $category)
        <category name="{{ $category['name'] }}">
            @foreach($category['products'] as $product)
                <product>
                    <id>{{ $product['id'] }}</id>
                    <name>{{ $product['name'] }}</name>
                    <price>{{ $product['price'] }}</price>
                </product>
            @endforeach
        </category>
    @endforeach
</catalog>

XML attributes

Add attributes using Blade variable syntax:
@foreach($notes as $note)
    <note 
        id="{{ $note['id'] }}" 
        priority="{{ $note['priority'] }}"
        @if($note['completed']) completed="true" @endif
    >
        <to>{{ $note['to'] }}</to>
        <from>{{ $note['from'] }}</from>
        <message>{{ $note['message'] }}</message>
    </note>
@endforeach

CDATA sections

Wrap content that may contain special characters:
@foreach($articles as $article)
    <article>
        <title>{{ $article['title'] }}</title>
        <content><![CDATA[{{ $article['content'] }}]]></content>
    </article>
@endforeach

Blade components

Reuse XML structures with Blade components:
{{-- resources/views/components/product-item.blade.php --}}
<product id="{{ $id }}">
    <name>{{ $name }}</name>
    <price>{{ $price }}</price>
    {{ $slot }}
</product>
{{-- resources/views/products.blade.php --}}
<products>
    @foreach($products as $product)
        <x-product-item :id="$product['id']" :name="$product['name']" :price="$product['price']">
            @if(isset($product['description']))
                <description>{{ $product['description'] }}</description>
            @endif
        </x-product-item>
    @endforeach
</products>

Escaping special characters

Blade automatically escapes HTML entities with {{ }}. For XML, this is usually what you want:
<note>
    <message>{{ $message }}</message> {{-- Escapes <, >, &, etc. --}}
</note>
If you need unescaped output (not recommended unless you trust the source), use {!! !!}:
<note>
    <html_content>{!! $trustedHtmlContent !!}</html_content>
</note>
Only use {!! !!} with trusted data. Unescaped content can break your XML structure.

Using view composers

Leverage Laravel’s view composers to automatically inject data:
// In a service provider
use Illuminate\Support\Facades\View;

public function boot()
{
    View::composer('xml.products', function ($view) {
        $view->with('timestamp', now()->toIso8601String());
    });
}
{{-- resources/views/xml/products.blade.php --}}
<products generated="{{ $timestamp }}">
    @foreach($products as $product)
        {{-- product markup --}}
    @endforeach
</products>

Performance considerations

Large datasets

For very large XML files, consider chunking your data:
// Instead of loading all records at once
$products = Product::all();

// Chunk the query
Product::chunk(1000, function ($products) {
    $xml = XML::exportView('products-chunk', ['products' => $products])
        ->disableRootTag()
        ->toString();
    
    // Append to file
    file_put_contents('products.xml', $xml, FILE_APPEND);
});

View caching

Laravel caches compiled Blade views, but you can also cache the final XML output:
use Illuminate\Support\Facades\Cache;

$xml = Cache::remember('products-xml', 3600, function () use ($data) {
    return XML::exportView('products', $data)
        ->setRootTag('catalog')
        ->toString();
});

How view exports work internally

The ViewExporter class extends XMLBuilder and renders your Blade view, wrapping it with XML prolog and root tags:
// Simplified from ViewExporter.php
public function __construct(string $viewName, array $data = [])
{
    parent::__construct();
    
    // Render the Blade view
    $this->view = view($viewName, $data)->render();
}

public function toString(): string
{
    return sprintf(
        "%s%s%s%s",
        $this->getProlog(),        // <?xml version="1.0" encoding="UTF-8"?>
        $this->openRootTag(),      // <root>
        $this->view,               // Your rendered Blade content
        $this->closeRootTag()      // </root>
    );
}

Debugging view exports

To debug what your Blade template generates before XML wrapping:
// Render the view directly
$rendered = view('files', $data)->render();
dd($rendered);

// Or use Ray/dump
ray(view('files', $data)->render());

Common patterns

<rss version="2.0">
    <channel>
        <title>{{ $feed['title'] }}</title>
        <link>{{ $feed['url'] }}</link>
        <description>{{ $feed['description'] }}</description>
        
        @foreach($items as $item)
            <item>
                <title>{{ $item['title'] }}</title>
                <link>{{ $item['url'] }}</link>
                <description>{{ $item['description'] }}</description>
                <pubDate>{{ $item['published_at']->toRssString() }}</pubDate>
            </item>
        @endforeach
    </channel>
</rss>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    @foreach($urls as $url)
        <url>
            <loc>{{ $url['location'] }}</loc>
            <lastmod>{{ $url['modified_at'] }}</lastmod>
            <changefreq>{{ $url['change_frequency'] }}</changefreq>
            <priority>{{ $url['priority'] }}</priority>
        </url>
    @endforeach
</urlset>
<configuration>
    <settings>
        @foreach($settings as $key => $value)
            <setting name="{{ $key }}">{{ $value }}</setting>
        @endforeach
    </settings>
    
    <features>
        @foreach($features as $feature => $enabled)
            <feature name="{{ $feature }}" enabled="{{ $enabled ? 'true' : 'false' }}" />
        @endforeach
    </features>
</configuration>

Best practices

Let Blade templates focus on XML structure. Keep business logic in controllers or services:
// Good: Logic in controller
$products = Product::with('category')
    ->where('active', true)
    ->get()
    ->map(fn($p) => [
        'id' => $p->id,
        'name' => $p->name,
        'price' => number_format($p->price, 2),
    ]);
    
$xml = XML::exportView('products', ['products' => $products]);
While whitespace doesn’t affect XML parsing, consistent indentation improves readability:
<products>
    @foreach($products as $product)
        <product>
            <name>{{ $product['name'] }}</name>
            <price>{{ $product['price'] }}</price>
        </product>
    @endforeach
</products>
For production exports, validate your XML against a schema:
$xml = XML::exportView('products', $data)->toString();

$dom = new \DOMDocument();
$dom->loadXML($xml);

if (!$dom->schemaValidate('path/to/schema.xsd')) {
    throw new \Exception('Invalid XML generated');
}

Exporting XML

Learn the basics of exporting XML from arrays

Custom transformers

Process XML data with custom transformer classes

Build docs developers (and LLMs) love