diff --git a/composer.json b/composer.json index 4d9642b..912349d 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "require": { "php": ">=7.2.0", "ext-zip": "*", - "ext-xmlreader" : "*" + "ext-xmlreader": "*", + "ext-dom": "*" }, "require-dev": { "phpunit/phpunit": "^8", diff --git a/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php b/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php index e95f186..ec83681 100644 --- a/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php +++ b/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php @@ -122,10 +122,15 @@ class CellValueFormatter */ protected function formatInlineStringCellValue($node) { - // inline strings are formatted this way: - // [INLINE_STRING] - $tNode = $node->getElementsByTagName(self::XML_NODE_INLINE_STRING_VALUE)->item(0); - $cellValue = $this->escaper->unescape($tNode->nodeValue); + // inline strings are formatted this way (they can contain any number of nodes): + // [INLINE_STRING][INLINE_STRING_2] + $tNodes = $node->getElementsByTagName(self::XML_NODE_INLINE_STRING_VALUE); + + $cellValue = ''; + for ($i = 0; $i < $tNodes->count(); $i++) { + $tNode = $tNodes->item($i); + $cellValue .= $this->escaper->unescape($tNode->nodeValue); + } return $cellValue; } diff --git a/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php b/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php index 34508b0..f981a63 100644 --- a/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php +++ b/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php @@ -186,18 +186,22 @@ class CellValueFormatterTest extends TestCase public function testFormatInlineStringCellValue($value, $expectedFormattedValue) { $nodeListMock = $this->createMock(\DOMNodeList::class); + $nodeListMock + ->expects($this->atLeastOnce()) + ->method('count') + ->willReturn(1); $nodeListMock ->expects($this->atLeastOnce()) ->method('item') ->with(0) - ->will($this->returnValue((object) ['nodeValue' => $value])); + ->willReturn((object) ['nodeValue' => $value]); $nodeMock = $this->createMock(\DOMElement::class); $nodeMock ->expects($this->atLeastOnce()) ->method('getElementsByTagName') ->with(CellValueFormatter::XML_NODE_INLINE_STRING_VALUE) - ->will($this->returnValue($nodeListMock)); + ->willReturn($nodeListMock); $formatter = new CellValueFormatter(null, null, false, false, new Escaper\XLSX()); $formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatInlineStringCellValue', $nodeMock); diff --git a/tests/Spout/Reader/XLSX/ReaderTest.php b/tests/Spout/Reader/XLSX/ReaderTest.php index 00fd16a..5b155b4 100644 --- a/tests/Spout/Reader/XLSX/ReaderTest.php +++ b/tests/Spout/Reader/XLSX/ReaderTest.php @@ -72,6 +72,19 @@ class ReaderTest extends TestCase } } + /** + * @return void + */ + public function testReadShouldSupportInlineStringsWithMultipleValueNodes() + { + $allRows = $this->getAllRowsForFile('sheet_with_multiple_value_nodes_in_inline_strings.xlsx'); + + $expectedRows = [ + ['VALUE 1 VALUE 2 VALUE 3 VALUE 4', 's1 - B1'], + ]; + $this->assertEquals($expectedRows, $allRows); + } + /** * @return void */ diff --git a/tests/resources/xlsx/sheet_with_multiple_value_nodes_in_inline_strings.xlsx b/tests/resources/xlsx/sheet_with_multiple_value_nodes_in_inline_strings.xlsx new file mode 100644 index 0000000..2ee574c Binary files /dev/null and b/tests/resources/xlsx/sheet_with_multiple_value_nodes_in_inline_strings.xlsx differ