Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Csv Laravel Package

league/csv

View on GitHub
Deep Wiki
Context7

layout: default title: Converting a CSV into a XML DOMDocument object description: The XMLConverter class converts a CSV records collection into an XML document using PHP's DOM extension capabilities

XML conversion

The XMLConverter converts a CSV records collection into a PHP DOMDocument.

Settings

Prior to converting your records collection into XML, you may wish to configure the element and its associated attribute names. To do so, XMLConverter provides methods to set up these settings.

XMLConverter::rootElement

public XMLConverter::rootElement(string $node_name): self

This method sets the XML root name.

XMLConverter::recordElement

public XMLConverter::recordElement(string $node_name, string $record_offset_attribute_name = ''): self

This method sets the XML record name and optionally the attribute name for the record offset value if you want this information preserved.

XMLConverter::fieldElement

public XMLConverter::fieldElement(?string $node_name, string $fieldname_attribute_name = ''): self

This method sets the XML field name and optionally the attribute name for the field name value. If the field name is null then the converter will use the CSV header names as field name.

If the field name is invalid an exception will be thrown. If you opt-in to use the record names as field element name, the exception will only be thrown on XML conversion. If you want to check if the CSV current header are usable as field name value you can use the new XMLConverter::supportsHeader method which returns false if at least on of the header name is invalid.

XMLConverter::supportsHeader(['foo', 'bar', '1']);   // returns false
XMLConverter::supportsHeader(['foo', 'bar', 'foo']); // returns true

XMLConverter::formatter

public XMLConverter::formatter(?callable $formatter): self

This method allow to apply a callback prior to converting your collection individual item. This callback allows you to specify how each item will be converted. The formatter should return an associative array suitable for conversion.

XMLConverter::when

This method allows to conditionally create your converter depending on the success or failure of a condition.

use League\Csv\XMLConverter;

$converter = (new XMLConverter());
if ($condition) {
    $converter = $converter->fieldElement(null);
} else {
    $converter = $converter->fieldElement('cell');
}

becomes

$stmt = (new XMLConverter())
    ->when(
        $condition,
        fn (XMLConverter $c) => $c->fieldElement(null),
        fn (XMLConverter $c) => $c->fieldElement('cell'),
    );
)

The else expression is not required but if present in MUST BE a callable which only accepts the XMLConverter instance and returns null or a XMLConverter instance.

The only requirements are:

  • that the condition is a boolean or a callable that returns a boolean.
  • the callback returns a XMLConverter instance or null.

Import

public XMLConverter::import(iterable $records, DOMDocument|\Dom\XMLDocument $doc): DOMElement|\Dom\Element

Instead of converting your tabular data into a full XML document you can now import it into an already existing DOMDocument object. To do so, you need to specify which document the data should be imported into using the XMLConverter::import method.

This method takes two arguments:

  • the tabular data as defined for the XMLConverter::convert method;
  • a DOMDocument or a \Dom\XmlDocument object to import the data into;

Note that the resulting DOMElement is attached to the given DOMDocument object but not yet included in the document tree. To include it, you still need to call a DOM insertion method like appendChild or insertBefore with a node that is currently in the document tree.

use League\Csv\XMLConverter;
use League\Csv\Statement;
use League\Csv\Reader;

$csv = Reader::from('/path/to/prenoms.csv', 'r');
$csv->setDelimiter(';');
$csv->setHeaderOffset(0);

$stmt = new Statement()
    ->where(function (array $record) {
        return 'Anaïs' === $record['prenoms'];
    })
    ->offset(0)
    ->limit(2)
;

$converter = new XMLConverter()
    ->rootElement('csv')
    ->recordElement('record', 'offset')
    ->fieldElement('field', 'name')
;

$records = $stmt->process($csv);

$dom = new DOMDocument('1.0');
$dom->loadXML('<root><header><name>My CSV Document</name></header></root>');

$data = $converter->import($records, $dom);
$dom->appendChild($data);
$dom->formatOutput = true;
$dom->encoding = 'iso-8859-15';

echo '<pre>', PHP_EOL;
echo htmlentities($dom->saveXML());
// <?xml version="1.0" encoding="iso-8859-15"?>
// <root>
//   <header>
//     <name>My CSV Document</name>
//   </header>
//   <csv>
//     <record offset="71">
//       <field name="prenoms">Anaïs</field>
//       <field name="nombre">137</field>
//       <field name="sexe">F</field>
//       <field name="annee">2004</field>
//     </record>
//     <record offset="1099">
//       <field name="prenoms">Anaïs</field>
//       <field name="nombre">124</field>
//       <field name="sexe">F</field>
//       <field name="annee">2005</field>
//     </record>
//   </csv>
// </root>

The result is different if you set the field element as null:

$converter = new XMLConverter()
    ->rootElement('csv')
    ->recordElement('record', 'offset')
    ->fieldElement(null)
;

$records = $stmt->process($csv);

$dom = new DOMDocument('1.0');
$dom->loadXML('<root><header><name>My CSV Document</name></header></root>');

$data = $converter->import($records, $dom);
$dom->appendChild($data);
$dom->formatOutput = true;
$dom->encoding = 'iso-8859-15';

echo '<pre>', PHP_EOL;
echo htmlentities($dom->saveXML());
// <?xml version="1.0" encoding="iso-8859-15"?>
// <root>
//   <header>
//     <name>My CSV Document</name>
//   </header>
//   <csv>
//     <record offset="71">
//       <prenoms>Anaïs</field>
//       <nombre>137</field>
//       <sexe>F</field>
//       <annee>2004</field>
//     </record>
//     <record offset="1099">
//       <prenoms>Anaïs</field>
//       <nombre>124</field>
//       <sexe>F</field>
//       <annee>2005</field>
//     </record>
//   </csv>
// </root>

Conversion

public XMLConverter::convert(iterable $records): DOMDocument

The XMLConverter::convert accepts an iterable which represents the records collection and returns a DOMDocument object.

use League\Csv\XMLConverter;
use League\Csv\Statement;
use League\Csv\Reader;

$csv = Reader::from('/path/to/prenoms.csv', 'r');
$csv->setDelimiter(';');
$csv->setHeaderOffset(0);

$stmt = new Statement()
    ->where(function (array $record) {
        return 'Anaïs' === $record['prenoms'];
    })
    ->offset(0)
    ->limit(2)
;

$converter = new XMLConverter()
    ->rootElement('csv')
    ->recordElement('record', 'offset')
    ->fieldElement('field', 'name')
;

$records = $stmt->process($csv);

$dom = $converter->convert($records);
$dom->formatOutput = true;
$dom->encoding = 'iso-8859-15';

echo '<pre>', PHP_EOL;
echo htmlentities($dom->saveXML());
// <?xml version="1.0" encoding="iso-8859-15"?>
// <csv>
//   <record offset="71">
//     <field name="prenoms">Anaïs</field>
//     <field name="nombre">137</field>
//     <field name="sexe">F</field>
//     <field name="annee">2004</field>
//   </record>
//   <record offset="1099">
//     <field name="prenoms">Anaïs</field>
//     <field name="nombre">124</field>
//     <field name="sexe">F</field>
//     <field name="annee">2005</field>
//   </record>
// </csv>

Download

To download the generated JSON you can use the XMLConverter::download method. The method returns the total number of bytes sent just like the XMLConverter::save method and enable downloading the XML on the fly.

General purpose

use League\Csv\Reader;
use League\Csv\XMLConverter;

$reader = Reader::from('file.csv');
$reader->setHeaderOffset(0);

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
header('Content-Type: text/xml; charset=UTF-8');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="name-for-your-file.xml"');

new XMLConverter()->download($reader);
die;

In this scenario, you have to specify all the headers for the file to be downloaded.

Using a filename

To download the generated XML on the fly you can use the XMLConverter::download method:

use League\Csv\Reader;
use League\Csv\XMLConverter;

$reader = Reader::from('file.csv');
$reader->setHeaderOffset(0);

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
 //the filename will be the name of the downloaded xml as shown by your HTTP client!
new XMLConverter()->download($reader, 'name-for-your-file.xml');
die;

By default, the method will set the encoding to utf-8 and will not format the XML. You can set those values using the method optional arguments.

use League\Csv\Reader;
use League\Csv\XMLConverter;

$reader = Reader::from('file.csv');
$reader->setHeaderOffset(0);

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
new XMLConverter()->download(
    records: $reader,
    filename: 'generated_file.xml',
    encoding: 'iso-8859-1',
    formatOutput: true,
);
die;
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport