Skip to content

Commit e78bca9

Browse files
authored
Merge pull request #4556 from oleibman/xmlspace
Xlsx Writer Eliminate xml:space From Non-Text Nodes
2 parents 8f7a401 + c326058 commit e78bca9

File tree

7 files changed

+134
-15
lines changed

7 files changed

+134
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). Thia is a
3636

3737
### Fixed
3838

39-
- Nothing yet.
39+
- Xlsx Writer eliminate xml:space from non-text nodes. [Issue #4542](https://github.com/PHPOffice/PhpSpreadsheet/issues/4542) [PR #4556](https://github.com/PHPOffice/PhpSpreadsheet/pull/4556)
4040

4141
## 2025-07-23 - 4.5.0
4242

src/PhpSpreadsheet/Writer/Xlsx.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
66
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
77
use PhpOffice\PhpSpreadsheet\HashTable;
8+
use PhpOffice\PhpSpreadsheet\RichText\RichText;
89
use PhpOffice\PhpSpreadsheet\Spreadsheet;
910
use PhpOffice\PhpSpreadsheet\Style\Borders;
1011
use PhpOffice\PhpSpreadsheet\Style\Conditional;
@@ -283,6 +284,19 @@ public function createStyleDictionaries(): void
283284
);
284285
}
285286

287+
/**
288+
* @return (RichText|string)[] $stringTable
289+
*/
290+
public function createStringTable(): array
291+
{
292+
$this->stringTable = [];
293+
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
294+
$this->stringTable = $this->getWriterPartStringTable()->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable);
295+
}
296+
297+
return $this->stringTable;
298+
}
299+
286300
/**
287301
* Save PhpSpreadsheet to file.
288302
*
@@ -303,10 +317,7 @@ public function save($filename, int $flags = 0): void
303317
Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
304318

305319
// Create string lookup table
306-
$this->stringTable = [];
307-
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
308-
$this->stringTable = $this->getWriterPartStringTable()->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable);
309-
}
320+
$this->createStringTable();
310321

311322
// Create styles dictionaries
312323
$this->createStyleDictionaries();

src/PhpSpreadsheet/Writer/Xlsx/Style.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ public function writeStyles(Spreadsheet $spreadsheet): string
3737

3838
// styleSheet
3939
$objWriter->startElement('styleSheet');
40-
$objWriter->writeAttribute('xml:space', 'preserve');
4140
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
4241

4342
// numFmts

src/PhpSpreadsheet/Writer/Xlsx/Table.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ public function writeTable(WorksheetTable $table, int $tableRef): string
3434
$range = $table->getRange();
3535

3636
$objWriter->startElement('table');
37-
$objWriter->writeAttribute('xml:space', 'preserve');
3837
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
3938
$objWriter->writeAttribute('id', (string) $tableRef);
4039
$objWriter->writeAttribute('name', $name);

src/PhpSpreadsheet/Writer/Xlsx/Workbook.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public function writeWorkbook(Spreadsheet $spreadsheet, bool $preCalculateFormul
3333

3434
// workbook
3535
$objWriter->startElement('workbook');
36-
$objWriter->writeAttribute('xml:space', 'preserve');
3736
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
3837
$objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
3938

src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ public function writeWorksheet(PhpspreadsheetWorksheet $worksheet, array $string
6868

6969
// Worksheet
7070
$objWriter->startElement('worksheet');
71-
$objWriter->writeAttribute('xml:space', 'preserve');
7271
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
7372
$objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
7473

@@ -1436,13 +1435,16 @@ private function writeCellInlineStr(XMLWriter $objWriter, string $mappedType, Ri
14361435
$objWriter->writeAttribute('t', $mappedType);
14371436
if (!$cellValue instanceof RichText) {
14381437
$objWriter->startElement('is');
1439-
$objWriter->writeElement(
1440-
't',
1441-
StringHelper::controlCharacterPHP2OOXML(
1442-
$cellValue
1443-
)
1438+
$objWriter->startElement('t');
1439+
$textToWrite = StringHelper::controlCharacterPHP2OOXML(
1440+
$cellValue
14441441
);
1445-
$objWriter->endElement();
1442+
if ($textToWrite !== trim($textToWrite)) {
1443+
$objWriter->writeAttribute('xml:space', 'preserve');
1444+
}
1445+
$objWriter->writeRawData($textToWrite);
1446+
$objWriter->endElement(); // t
1447+
$objWriter->endElement(); // is
14461448
} else {
14471449
$objWriter->startElement('is');
14481450
$this->getParentWriter()
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
9+
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
10+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
11+
use PHPUnit\Framework\TestCase;
12+
13+
class Issue4542Test extends TestCase
14+
{
15+
public function testXmlSpace(): void
16+
{
17+
$spreadsheet = new Spreadsheet();
18+
$sheet = $spreadsheet->getActiveSheet();
19+
$string = ' Ye&ar ';
20+
$trimString = trim($string);
21+
$sheet->getCell('A1')->setValue($string);
22+
$sheet->getCell('A2')->setValueExplicit($string, DataType::TYPE_INLINE);
23+
$sheet->getCell('B1')->setValue($trimString);
24+
$sheet->getCell('B2')->setValueExplicit($trimString, DataType::TYPE_INLINE);
25+
$writer = new XlsxWriter($spreadsheet);
26+
27+
$writer->createStyleDictionaries();
28+
$writerStyle = new XlsxWriter\Style($writer);
29+
$data = $writerStyle->writeStyles($spreadsheet);
30+
self::assertStringContainsString(
31+
'<styleSheet',
32+
$data
33+
);
34+
self::assertStringNotContainsString(
35+
'xml:space',
36+
$data
37+
);
38+
39+
$writerWorkbook = new XlsxWriter\Workbook($writer);
40+
$data = $writerWorkbook->writeWorkbook($spreadsheet);
41+
self::assertStringContainsString(
42+
'<workbook',
43+
$data
44+
);
45+
self::assertStringNotContainsString(
46+
'xml:space',
47+
$data
48+
);
49+
50+
$stringTable = $writer->createStringTable();
51+
$writerStringTable = new XlsxWriter\StringTable($writer);
52+
$data = $writerStringTable->writeStringTable($stringTable);
53+
self::assertStringContainsString(
54+
'<si><t xml:space="preserve"> Ye&amp;ar </t></si>',
55+
$data
56+
);
57+
self::assertStringContainsString(
58+
'<si><t>Ye&amp;ar</t></si>',
59+
$data
60+
);
61+
62+
$writerWorksheet = new XlsxWriter\Worksheet($writer);
63+
$data = $writerWorksheet->writeWorksheet($sheet, []);
64+
self::assertStringContainsString(
65+
'<c r="A2" t="inlineStr"><is><t xml:space="preserve"> Ye&amp;ar </t></is></c>',
66+
$data
67+
);
68+
self::assertStringContainsString(
69+
'<c r="B2" t="inlineStr"><is><t>Ye&amp;ar</t></is></c>',
70+
$data
71+
);
72+
73+
$spreadsheet->disconnectWorksheets();
74+
}
75+
76+
public function testTable(): void
77+
{
78+
$spreadsheet = new Spreadsheet();
79+
$sheet = $spreadsheet->getActiveSheet();
80+
$sheet->fromArray(
81+
[
82+
['MyCol', 'Colonne2', 'Colonne3'],
83+
[10, 20],
84+
[2],
85+
[3],
86+
[4],
87+
],
88+
null,
89+
'B1',
90+
true
91+
);
92+
$table = new Table('B1:D5', 'Tableau1');
93+
$sheet->addTable($table);
94+
95+
$writer = new XlsxWriter($spreadsheet);
96+
$writerTable = new XlsxWriter\Table($writer);
97+
$data = $writerTable->writeTable($table, 1);
98+
99+
self::assertStringContainsString(
100+
'<table ',
101+
$data
102+
);
103+
self::assertStringNotContainsString(
104+
'xml:space',
105+
$data
106+
);
107+
$spreadsheet->disconnectWorksheets();
108+
}
109+
}

0 commit comments

Comments
 (0)