From c91bae3fed220878d623dc6a97877cf815a67e18 Mon Sep 17 00:00:00 2001
From: oleibman <10341515+oleibman@users.noreply.github.com>
Date: Mon, 14 Sep 2026 07:39:37 -0700
Subject: [PATCH] Minor Xml Reader Improvements
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Six years ago, my PR #1557 was merged. It was written mainly to improve code coverage in Xml Reader, but some changes and enhancements were made to the Reader code. I noted in that ticket: "File templates/Excel2003XMLTest.xml, used in some tests, is not
readable by a current version of Excel. I have substituted a new file
excel2003.xml to be used in its place. I have not deleted the original
in case someone in future (possibly me) wants to see what it needs to
make it usable." That time has finally arrived.
Excel could not open the file. LibreOffice could, and did a pretty decent job, but something seemed wrong with how it handled formulas. PhpSpreadsheet could not read it, because a field identified as a date/timestamp was wrong - it specified a time-of-day hour as `288`. I made a copy of the file, changed the invalid hour to something valid. It turns out that was not Excel's problem - it still could not read the file. But, for the first time that I can recall, Excel produced decent diagnostic messages! They were in a location that you can't get to through Windows Explorer, even with "hide system files" turned off. However, you could get to it through Windows Command Prompt. There were 56 problems, all involving formulas (which was probably LibreOffice's problem). The formulas were all of the form:
```
of:=[.B1]+[.C1]
```
Now, XML spreadsheets use RC format rather than A1 format for its cells. The formula above is of a style that LibreOffice uses, but Excel does not understand it. It is looking for something like:
```
ss:Formula="=RC[-6]+RC[-5]
```
Excel2003Xml doesn't understand the formula in the file, but PhpSpreadsheet does. But, before it could do so, we had to eliminate the Exception when we tried to parse the invalid date/time. So, the first order of business was to wrap the Xml Reader date conversion logic in a try/catch. This allowed PhpSpreadsheet to read the file, and then to save it as an Xlsx file. Then we could open the Xlsx file in Excel, and save it as Xml. Voilà. We have converted the unreadable Xml file to a readable one. LibreOffice can also read the new file, and the formulas are now correct. BTW, I have no idea what was intended on sheet "Report Data" cells G17:G29. They all subtract a value from an empty cell, so the result is always negative, and try to format it as a date (which Excel doesn't like for negative numbers). Whatever that problem is, there is no need to fix it at this time.
At this point, a little cleanup was still needed. The Xml file was using some strange named styles, e.g. `Medium Date`. I was able to get a list of these with the google query `excel 2003 ooxml named number formats`. However, the list came only in the AI portion of the response; I could not find a link to anything permanent. So I went with what it showed me.
The earlier PR suggested that handling UTF-16 for this format would be difficult. However, saving the now-usable UTF-8 Xml file as UTF-16 with BOM results in a file which PhpSpreadsheet (and Excel and LibreOffice) can read without any code changes.
---
src/PhpSpreadsheet/Reader/Xml.php | 21 +-
src/PhpSpreadsheet/Reader/Xml/Style.php | 5 +-
.../Reader/Xml/Style/NumberFormat.php | 48 +-
.../Reader/Xml/BadDateTest.php | 87 ++
.../Reader/Xml/Excel2003XMLTest.corrected.xml | 1315 +++++++++++++++++
.../data/Reader/Xml}/Excel2003XMLTest.xml | 0
tests/data/Reader/Xml/formats.utf16lebom.xml | Bin 0 -> 10182 bytes
tests/data/Reader/Xml/formats.xml | 141 ++
8 files changed, 1602 insertions(+), 15 deletions(-)
create mode 100644 tests/PhpSpreadsheetTests/Reader/Xml/BadDateTest.php
create mode 100644 tests/data/Reader/Xml/Excel2003XMLTest.corrected.xml
rename {samples/templates => tests/data/Reader/Xml}/Excel2003XMLTest.xml (100%)
create mode 100644 tests/data/Reader/Xml/formats.utf16lebom.xml
create mode 100644 tests/data/Reader/Xml/formats.xml
diff --git a/src/PhpSpreadsheet/Reader/Xml.php b/src/PhpSpreadsheet/Reader/Xml.php
index f5cdc8108..46d8f69f5 100644
--- a/src/PhpSpreadsheet/Reader/Xml.php
+++ b/src/PhpSpreadsheet/Reader/Xml.php
@@ -39,6 +39,9 @@ class Xml extends BaseReader
*/
protected array $styles = [];
+ /** @var string[] */
+ private array $numberFormatMappings = Style\NumberFormat::FORMAT_MAPPINGS;
+
/**
* Create a new Excel2003XML Reader instance.
*/
@@ -301,7 +304,7 @@ class Xml extends BaseReader
(new Properties($spreadsheet))->readProperties($xml, $namespaces);
- $this->styles = (new Style())->parseStyles($xml, $namespaces);
+ $this->styles = (new Style())->parseStyles($xml, $namespaces, $this->numberFormatMappings);
if (isset($this->styles['Default']) && is_array($this->styles['Default'])) {
$spreadsheet->getCellXfCollection()[0]->applyFromArray($this->styles['Default']);
}
@@ -507,8 +510,13 @@ class Xml extends BaseReader
break;
case 'DateTime':
$type = DataType::TYPE_NUMERIC;
- $dateTime = new DateTime($cellValue, new DateTimeZone('UTC'));
- $cellValue = Date::PHPToExcel($dateTime);
+
+ try {
+ $dateTime = new DateTime($cellValue, new DateTimeZone('UTC'));
+ $cellValue = Date::PHPToExcel($dateTime);
+ } catch (Throwable) {
+ $type = DataType::TYPE_STRING;
+ }
break;
case 'Error':
@@ -755,4 +763,11 @@ class Xml extends BaseReader
? new SimpleXMLElement('')
: ($simple->attributes($node) ?? new SimpleXMLElement(''));
}
+
+ public function setNumberFormatMapping(string $key, string $value): self
+ {
+ $this->numberFormatMappings[$key] = $value;
+
+ return $this;
+ }
}
diff --git a/src/PhpSpreadsheet/Reader/Xml/Style.php b/src/PhpSpreadsheet/Reader/Xml/Style.php
index 699d71828..f4ab459b8 100644
--- a/src/PhpSpreadsheet/Reader/Xml/Style.php
+++ b/src/PhpSpreadsheet/Reader/Xml/Style.php
@@ -16,10 +16,11 @@ class Style
/**
* @param string[] $namespaces
+ * @param string[] $numberFormatMappings
*
* @return mixed[]
*/
- public function parseStyles(SimpleXMLElement $xml, array $namespaces): array
+ public function parseStyles(SimpleXMLElement $xml, array $namespaces, array $numberFormatMappings = Style\NumberFormat::FORMAT_MAPPINGS): array
{
$children = $xml->children('urn:schemas-microsoft-com:office:spreadsheet');
$stylesXml = $children->Styles[0];
@@ -70,7 +71,7 @@ class Style
break;
case 'NumberFormat':
if ($styleAttributes) {
- $numberFormat = $numberFormatStyleParser->parseStyle($styleAttributes);
+ $numberFormat = $numberFormatStyleParser->parseStyle($styleAttributes, $numberFormatMappings);
}
break;
diff --git a/src/PhpSpreadsheet/Reader/Xml/Style/NumberFormat.php b/src/PhpSpreadsheet/Reader/Xml/Style/NumberFormat.php
index 1ca825a54..d852e66c0 100644
--- a/src/PhpSpreadsheet/Reader/Xml/Style/NumberFormat.php
+++ b/src/PhpSpreadsheet/Reader/Xml/Style/NumberFormat.php
@@ -2,12 +2,40 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xml\Style;
+use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
+use PhpOffice\PhpSpreadsheet\Style\NumberFormat as Format;
use SimpleXMLElement;
class NumberFormat extends StyleBase
{
- /** @return mixed[] */
- public function parseStyle(SimpleXMLElement $styleAttributes): array
+ /** @internal */
+ public const FORMAT_MAPPINGS = [
+ 'Euro Currency' => '€#,##0.00;[Red](€#,##0.00)',
+ 'Fixed' => Format::FORMAT_NUMBER_00,
+ 'General' => '',
+ 'General Number' => '',
+ 'General Date' => Format::FORMAT_DATE_DATETIME_BETTER,
+ 'Long Date' => Format::FORMAT_DATE_LONG_DATE,
+ 'Long Time' => Format::FORMAT_DATE_TIME2,
+ 'Medium Date' => Format::FORMAT_DATE_XLSX15_YYYY,
+ 'Medium Time' => Format::FORMAT_DATE_TIME1,
+ 'Percent' => Format::FORMAT_PERCENTAGE_00,
+ 'Scientific' => '0.00E+00',
+ 'Short Date' => Format::FORMAT_DATE_YYYYMMDD,
+ 'Short Time' => Format::FORMAT_DATE_TIME1,
+ 'Standard' => Format::FORMAT_NUMBER_COMMA_SEPARATED1,
+ // N.B. - following formats apply to numbers, not booleans
+ 'True/False' => '"True";"True";"False"',
+ 'Yes/No' => '"Yes";"Yes";"No"',
+ 'On/Off' => '"On";"On";"Off"',
+ ];
+
+ /**
+ * @param string[] $numberFormatMappings expected to be FORMAT_MAPPINGS, but individual entries can be overridden
+ *
+ * @return mixed[]
+ */
+ public function parseStyle(SimpleXMLElement $styleAttributes, array $numberFormatMappings = self::FORMAT_MAPPINGS): array
{
$style = [];
@@ -15,16 +43,16 @@ class NumberFormat extends StyleBase
$toFormats = ['-', ' '];
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
- $styleAttributeValue = str_replace($fromFormats, $toFormats, (string) $styleAttributeValue);
-
- switch ($styleAttributeValue) {
- case 'Short Date':
- $styleAttributeValue = 'dd/mm/yyyy';
-
- break;
+ $styleAttributeValue = (string) $styleAttributeValue;
+ $styleAttributeValue = str_replace($fromFormats, $toFormats, $styleAttributeValue);
+ if (array_key_exists($styleAttributeValue, $numberFormatMappings)) {
+ $styleAttributeValue = $numberFormatMappings[$styleAttributeValue];
+ } elseif ($styleAttributeValue === 'Currency') {
+ $currencyCode = StringHelper::getCurrencyCode();
+ $styleAttributeValue = "{$currencyCode}#,##0.00;[Red]({$currencyCode}#,##0.00)";
}
- if ($styleAttributeValue > '') {
+ if ($styleAttributeValue !== '') {
$style['numberFormat']['formatCode'] = $styleAttributeValue;
}
}
diff --git a/tests/PhpSpreadsheetTests/Reader/Xml/BadDateTest.php b/tests/PhpSpreadsheetTests/Reader/Xml/BadDateTest.php
new file mode 100644
index 000000000..d0ad37372
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Reader/Xml/BadDateTest.php
@@ -0,0 +1,87 @@
+load($filename);
+ $sheet = $spreadsheet->getSheetByNameOrThrow('Sample Data');
+ self::assertSame('1960-12-19', $sheet->getCell('A10')->getFormattedValue());
+ self::assertSame('1.50', $sheet->getCell('A11')->getFormattedValue());
+ self::assertSame('2:30 AM', $sheet->getCell('A13')->getFormattedValue());
+ self::assertSame('1960-12-19 01:30', $sheet->getCell('A15')->getFormattedValue());
+ $sheet = $spreadsheet->getSheetByNameOrThrow('Report Data');
+ self::assertSame('11-Nov-2011', $sheet->getCell('D27')->getFormattedValue());
+ self::assertSame('11:00 AM', $sheet->getCell('E27')->getFormattedValue());
+ self::assertSame('12-Dec-2012', $sheet->getCell('D28')->getFormattedValue());
+ self::assertSame('1899-12-31T288:00:00.000', $sheet->getCell('E28')->getValue(), 'invalid date/time-stamp treated as plain string');
+ $spreadsheet->disconnectWorksheets();
+ }
+
+ /** @return string[][] */
+ public static function providerXmlSpreadsheet(): array
+ {
+ return [
+ 'spreadsheet with bad datetimestamp and formulas' => ['tests/data/Reader/Xml/Excel2003XMLTest.xml'],
+ 'spreadsheet with formulas corrected' => ['tests/data/Reader/Xml/Excel2003XMLTest.corrected.xml'],
+ ];
+ }
+
+ public function testFormats(): void
+ {
+ $reader = new Xml();
+ $reader
+ ->setNumberFormatMapping('Currency', '¥#,##0;[Red](¥#,##0)')
+ ->setNumberFormatMapping('Yes/No', '"Oui";"Oui";"Non"')
+ ->setNumberFormatMapping('On/Off', '"Marche";"Marche";"Arrêt"');
+ $filename = 'tests/data/Reader/Xml/formats.xml';
+ $spreadsheet = $reader->load($filename);
+ $sheet = $spreadsheet->getActiveSheet();
+ $expected = [
+ ['True/False', 'True', 'False'],
+ ['Yes/No', 'Oui', 'Non'],
+ ['On/Off', 'Marche', 'Arrêt'],
+ ['Long Time', '6:00:00 PM', null],
+ ['Percent', '97.00%', null],
+ ['Currency', '(¥1,235)', null],
+ ['Standard', '1,234.57', null],
+ ['Fixed', '1234.58', null],
+ ['Euro Currency', '(€1,234.59)', null],
+ ['Scientific', '-1.23E+3', null],
+ ];
+ self::assertSame($expected, $sheet->toArray());
+ $spreadsheet->disconnectWorksheets();
+ }
+
+ public function testUtf16(): void
+ {
+ $reader = new Xml();
+ $filename = 'tests/data/Reader/Xml/formats.utf16lebom.xml';
+ $spreadsheet = $reader->load($filename);
+ $sheet = $spreadsheet->getActiveSheet();
+ $expected = [
+ ['True/False', 'True', 'False'],
+ ['Yes/No', 'Yes', 'No'],
+ ['On/Off', 'On', 'Off'],
+ ['Long Time', '6:00:00 PM', null],
+ ['Percent', '97.00%', null],
+ ['Currency', '($1,234.56)', null],
+ ['Standard', '1,234.57', null],
+ ['Fixed', '1234.58', null],
+ ['Euro Currency', '(€1,234.59)', null],
+ ['Scientific', '-1.23E+3', null],
+ ];
+ self::assertSame($expected, $sheet->toArray());
+ $spreadsheet->disconnectWorksheets();
+ }
+}
diff --git a/tests/data/Reader/Xml/Excel2003XMLTest.corrected.xml b/tests/data/Reader/Xml/Excel2003XMLTest.corrected.xml
new file mode 100644
index 000000000..f674775b5
--- /dev/null
+++ b/tests/data/Reader/Xml/Excel2003XMLTest.corrected.xml
@@ -0,0 +1,1315 @@
+
+
+
+
+Untitled Spreadsheet
+Unknown Creator
+Owen Leibman
+2026-09-13T08:18:02Z
+2026-09-13T08:18:02Z
+16.00
+
+
+
+
+
+6510
+19200
+32767
+32767
+False
+False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+|
+Test String 1
+
+
+
Test for a simple colour-formatted string
+
+
+ |
+
+1
+ |
+
+5
+ |
+
+A
+ |
+
+E
+ |
+
+6
+ |
+
+AE
+ |
+
+PhpSpreadsheet
+ |
+
+
+|
+Test - String 2
+ |
+
+2
+ |
+
+6
+ |
+
+B
+ |
+
+F
+ |
+
+8
+ |
+
+BF
+ |
+
+Dot
+ |
+
+
+|
+Test #3
+ |
+
+3
+ |
+
+7
+ |
+
+C
+ |
+
+G
+ |
+
+10
+ |
+
+CG
+ |
+
+Red
+ |
+
+Red
+ |
+
+Dash
+ |
+
+
+|
+Test with (") in string
+ |
+
+4
+ |
+
+8
+ |
+
+D
+ |
+
+H
+ |
+
+12
+ |
+
+DH
+ |
+
+Orange
+ |
+
+Orange
+ |
+
+Dash/Dot/Dot
+ |
+
+
+|
+10
+ |
+
+26
+ |
+
+36
+ |
+
+Yellow
+ |
+
+Yellow
+ |
+
+Dash/Dot
+ |
+
+
+|
+Test #3
+ |
+
+1.23
+ |
+
+1
+ |
+
+1
+ |
+
+Green
+ |
+
+Green
+ |
+
+Thin Line
+ |
+
+
+|
+Test #3
+ |
+
+2.34
+ |
+
+0
+ |
+
+0
+ |
+
+#NAME?
+ |
+
+Blue
+ |
+
+Blue
+ |
+
+Thick Dash/Dot/Dot
+ |
+
+
+|
+Test #3
+ |
+
+3.45
+ |
+
+Purple
+ |
+
+Purple
+ |
+
+Variant Thick Dash/Dot/Dot
+ |
+
+
+|
+Pink
+ |
+
+Pink
+ |
+
+Thick Dash/Dot
+ |
+
+
+|
+1960-12-19T00:00:00.000
+ |
+
+TOP
+ |
+
+0
+ |
+
+Brown
+ |
+
+Brown
+ |
+
+Thick Dash
+ |
+
+
+|
+1.5
+ |
+
+#DIV/0!
+ |
+
+Thick Line
+ |
+
+
+|
+BOTTOM
+ |
+
+Extra Thick Line
+ |
+
+
+|
+1900-01-01T02:30:00.000
+ |
+
+Мойва сушеная
+
+
+
Tests for UTF-8 content
+
+
+ |
+
+Double Line
+ |
+
+
+|
+LEFT
+ |
+
+Ärendetext
+ |
+
+
+|
+1960-12-19T01:30:00.000
+ |
+
+Højde
+ |
+
+
+|
+RIGHT
+ |
+
+
+|
+BOX
+ |
+
+Test Column 1
+ |
+ |
+ |
+
+
+ |
+
+Test Column 2
+ |
+ |
+
+Patterned
+ |
+
+Patterned 2
+ |
+
+
+ |
+ |
+
+Test Column 3
+ |
+
+
+|
+Underline None
+ |
+
+Rotate 90
+ |
+
+Rotate 45
+ |
+
+Rotate -90
+ |
+
+Rotate -45
+ |
+ |
+
+
+|
+Underline 1
+ |
+
+Subscript
+ |
+ |
+
+
+|
+Underline 2
+ |
+
+Superscript
+ |
+ |
+
+
+|
+Underline 3
+ |
+ |
+
+
+|
+Underline 4
+ |
+ |
+
+
+|
+
+I don't know if Gnumeric supports
+
+
Rich Text
+
+
in the same way as
+
+
Excel
+
+
, And this row should be autofit height with text wrap
+
+ |
+
+
+|
+PhpSpreadsheet
+ |
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+9
+
+600
+600
+
+
+False
+False
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+|
+Heading 1
+ |
+
+Heading 2
+ |
+
+Third Heading
+ |
+
+Date Heading
+ |
+
+Time Heading
+ |
+
+Adjusted Date
+ |
+
+Adjusted Number
+ |
+ |
+
+
+ |
+
+Adjusted Number
+ |
+
+Third Heading
+ |
+
+
+|
+1
+ |
+
+1.1100000000000001
+ |
+
+1.1100000000000001
+ |
+
+
+|
+2
+ |
+
+4.4400000000000004
+ |
+
+2.2200000000000002
+ |
+
+
+|
+3
+ |
+
+9.99
+ |
+
+3.33
+ |
+
+
+|
+4
+ |
+
+17.760000000000002
+ |
+
+4.4400000000000004
+ |
+
+
+|
+5
+ |
+
+27.75
+ |
+
+5.55
+ |
+
+
+|
+6
+ |
+
+39.96
+ |
+
+6.66
+ |
+
+
+|
+7
+ |
+
+54.39
+ |
+
+7.77
+ |
+
+
+|
+8
+ |
+
+71.040000000000006
+ |
+
+8.8800000000000008
+ |
+
+
+|
+9
+ |
+
+89.91
+ |
+
+9.99
+ |
+
+
+|
+10
+ |
+
+111
+ |
+
+11.1
+ |
+
+
+|
+11
+ |
+
+134.31
+ |
+
+12.21
+ |
+
+
+|
+12
+ |
+
+159.84
+ |
+
+13.32
+ |
+
+
+|
+13
+ |
+
+1.1100000000000001
+ |
+
+-1.1100000000000001
+ |
+
+
+|
+ABC
+ |
+
+1
+ |
+
+1.1100000000000001
+ |
+
+2001-01-01T00:00:00.000
+ |
+
+1900-01-01T01:00:00.000
+ |
+
+#VALUE!
+ |
+
+#VALUE!
+ |
+
+A
+ |
+
+Adjusted Number
+ |
+
+
+|
+BCD
+ |
+
+2
+ |
+
+2.2200000000000002
+ |
+
+2002-02-02T00:00:00.000
+ |
+
+1900-01-01T02:00:00.000
+ |
+
+1899-12-29T21:21:36.000
+ |
+
+1.2321000000000002
+ |
+
+B
+ |
+
+1.11
+ |
+
+
+|
+CDE
+ |
+
+3
+ |
+
+3.33
+ |
+
+2003-03-03T00:00:00.000
+ |
+
+1900-01-01T03:00:00.000
+ |
+
+1899-12-26T13:26:24.000
+ |
+
+9.8568000000000016
+ |
+
+C
+ |
+
+4.44
+ |
+
+
+|
+DEF
+ |
+
+4
+ |
+
+4.4400000000000004
+ |
+
+2004-04-03T23:00:00.000
+ |
+
+1900-01-01T04:00:00.000
+ |
+
+1899-12-21T00:14:24.000
+ |
+
+33.2667
+ |
+
+D
+ |
+
+9.99
+ |
+
+
+|
+EFG
+ |
+
+5
+ |
+
+5.55
+ |
+
+2005-05-04T23:00:00.000
+ |
+
+1900-01-01T05:00:00.000
+ |
+
+1899-12-13T05:45:36.000
+ |
+
+78.854400000000012
+ |
+
+E
+ |
+
+17.76
+ |
+
+
+|
+FGH
+ |
+
+6
+ |
+
+6.66
+ |
+
+2006-06-05T23:00:00.000
+ |
+
+1900-01-01T06:00:00.000
+ |
+
+1899-12-03T06:00:00.000
+ |
+
+154.01249999999999
+ |
+
+F
+ |
+
+27.75
+ |
+
+
+|
+GHI
+ |
+
+7
+ |
+
+7.77
+ |
+
+2007-07-06T23:00:00.000
+ |
+
+1900-01-01T07:00:00.000
+ |
+
+1899-11-21T00:57:36.000
+ |
+
+266.1336
+ |
+
+G
+ |
+
+39.96
+ |
+
+
+|
+HIJ
+ |
+
+8
+ |
+
+8.8800000000000008
+ |
+
+2008-08-07T23:00:00.000
+ |
+
+1900-01-01T08:00:00.000
+ |
+
+1899-11-06T14:38:24.000
+ |
+
+422.6103
+ |
+
+H
+ |
+
+54.39
+ |
+
+
+|
+IJK
+ |
+
+9
+ |
+
+9.99
+ |
+
+2009-09-08T23:00:00.000
+ |
+
+1900-01-01T09:00:00.000
+ |
+
+1899-10-20T23:02:24.000
+ |
+
+630.8352000000001
+ |
+
+I
+ |
+
+71.04
+ |
+
+
+|
+JKL
+ |
+
+10
+ |
+
+11.1
+ |
+
+2010-10-09T23:00:00.000
+ |
+
+1900-01-01T10:00:00.000
+ |
+
+1899-10-02T02:09:36.000
+ |
+
+898.20089999999993
+ |
+
+J
+ |
+
+89.91
+ |
+
+
+|
+KLM
+ |
+
+11
+ |
+
+12.21
+ |
+
+2011-11-11T00:00:00.000
+ |
+
+1900-01-01T11:00:00.000
+ |
+
+1899-09-11T00:00:00.000
+ |
+
+1232.0999999999999
+ |
+
+K
+ |
+
+111
+ |
+
+
+|
+LMN
+ |
+
+12
+ |
+
+13.32
+ |
+
+2012-12-12T00:00:00.000
+ |
+
+1899-12-31T288:00:00.000
+ |
+
+1899-08-18T16:33:36.000
+ |
+
+1639.9251000000002
+ |
+
+L
+ |
+
+134.31
+ |
+
+
+|
+ZYX
+ |
+
+-1
+ |
+
+-1.1100000000000001
+ |
+
+1999-12-01T00:00:00.000
+ |
+
+1900-01-01T23:00:00.000
+ |
+
+1899-07-24T03:50:24.000
+ |
+
+2129.0688
+ |
+
+M
+ |
+
+159.84
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+9
+
+600
+600
+
+False
+False
+
+
+
diff --git a/samples/templates/Excel2003XMLTest.xml b/tests/data/Reader/Xml/Excel2003XMLTest.xml
similarity index 100%
rename from samples/templates/Excel2003XMLTest.xml
rename to tests/data/Reader/Xml/Excel2003XMLTest.xml
diff --git a/tests/data/Reader/Xml/formats.utf16lebom.xml b/tests/data/Reader/Xml/formats.utf16lebom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9e01964c44b565d348cd79555d6ffd0a6756ae67
GIT binary patch
literal 10182
zcmdT~+j1I55bbAw1*JSo2;Gn?%d5fY@=~96%BY7Z(>>^2aARXPWlRE{nLW
zET}D^-JPDEp3^;jnc4sTEy`v
zI^$6q8+`|;g)=H(cIk}L`i|@L7(>i6ol%BPpYyT12mZ7nj>`KH`V}OL>#Mu=@Ouag
zpsw%mwk}otR^>v<(3|x>a<)cG%fQyoLEV7C5
zER^OABpE?c&Y&a}%!g8CzMSDVho?I3PoalnTm?Bo>z_`-cwgiB9=!beFM-F2TmSp6SG-lVlwC+q
zrqfEWHsboNVRTwf8#vzmVBL0LyM5^NMy};o=+NZNLeqXV&y(1Cd7t7Wd^9iYvxYXSm{sTM?!66TM
z^3J-#kvz?84j&ibKpNwq-h->9fjQLhH^7SKJtIsDl$Tgd9oSvV$uplmnR7Ug;T*1U
zT5_ZZnQcF2VU+(7($WX|Ir_I5ydPrCzr*UJUpxopE#@~yA4Xqmzs5WISJGTN-$p;y
z!IN=S-^VzAhjnSb*!rta;F@I?p#J|C@ZmaUEZ+IPmedQfZ2&7$KV$1m+b+>YKX1J4
zIh3*NMxnnQU`)>A0kfp$m=AP-31?EnN^Uy@{7h?j^KCNI9PHP(lrb(>|G@SA$yqfm
zn^#=^cTPe|&m3tGo82|=?Ls!TQ~Cj(=%J(Yj9QlFTAqUX_j)uf6oYq$kLh-ZHFN+;
zjg}fS?2Oi)e>9etkYpB?v(O4KuGCOJt08x|!N`@79VJ=evdDb|
zYD3`06}~=VM;nUR8Ddgeh*hx8E%vXE*l`T8W%YLjy)h@sU=6h4Q(7r#@nlVzZk(56
zWk;XAK1TU9EN(uMp&;i$l@v6g@a?eHA9;+s;&pD^0jEweTJjgE_a5sFz
zF>M^5^G@frPfHc9drFmaqrR*RS{Kigf#|5_LO=d8x(su~bakj1_RH#U6&bcqhhf&5
zt`0Tle_0)_BE$CSa5~pdSCblzp4O!LtyWNN(5s%JzOtR=T}0s=+WEHNYE=E@X%VkQ
zWG2m~c)w^hvxxMI$1tt5o<=+#!}by7&n7#g+Z09ObxyiSYK^!Yl6n$yILX9Lw$3u+
zRZ6;uYPGf;qC8nLJazAWn=I5Q+lVi0~>W1$_bct7(oAT72
z<3`_^M9Sw4X3IH$0Wb5L_QgR`o9}HF5|tu+Yx|ET@c=rrGyMv76#t&gdfv%
+
+
+
+ Owen Leibman
+ Owen Leibman
+ 2026-09-12T08:55:46Z
+ 16.00
+
+
+
+
+
+ 6510
+ 19200
+ 32767
+ 32767
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | True/False |
+ 1 |
+ 0 |
+
+
+ | Yes/No |
+ 1 |
+ 0 |
+
+
+ | On/Off |
+ 1 |
+ 0 |
+
+
+ | Long Time |
+ 1899-12-31T18:00:00.000 |
+
+
+ | Percent |
+ 0.97 |
+
+
+ | Currency |
+ -1234.56 |
+
+
+ | Standard |
+ 1234.57 |
+
+
+ | Fixed |
+ 1234.58 |
+
+
+ | Euro Currency |
+ -1234.5899999999999 |
+
+
+ | Scientific |
+ -1234.5899999999999 |
+
+
+
+
+
+
+
+
+
+
+
+ 600
+ 600
+
+
+
+
+ 3
+ 10
+
+
+ False
+ False
+
+
+