diff --git a/src/PhpSpreadsheet/Reader/Xml.php b/src/PhpSpreadsheet/Reader/Xml.php index 11aa1df3bd..9de882337f 100644 --- a/src/PhpSpreadsheet/Reader/Xml.php +++ b/src/PhpSpreadsheet/Reader/Xml.php @@ -191,7 +191,7 @@ public function listWorksheetNames($pFilename) $xml_ss = $xml->children($namespaces['ss']); foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = $worksheet->attributes($namespaces['ss']); + $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); $worksheetNames[] = (string) $worksheet_ss['Name']; } @@ -221,7 +221,7 @@ public function listWorksheetInfo($pFilename) $worksheetID = 1; $xml_ss = $xml->children($namespaces['ss']); foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = $worksheet->attributes($namespaces['ss']); + $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); $tmpInfo = []; $tmpInfo['worksheetName'] = ''; @@ -381,13 +381,13 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) } if (isset($xml->CustomDocumentProperties)) { foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { - $propertyAttributes = $propertyValue->attributes($namespaces['dt']); + $propertyAttributes = self::getAttributes($propertyValue, $namespaces['dt']); $propertyName = preg_replace_callback('/_x([0-9a-f]{4})_/i', ['self', 'hex2str'], $propertyName); $propertyType = Properties::PROPERTY_TYPE_UNKNOWN; switch ((string) $propertyAttributes) { case 'string': $propertyType = Properties::PROPERTY_TYPE_STRING; - $propertyValue = trim($propertyValue); + $propertyValue = trim((string) $propertyValue); break; case 'boolean': @@ -407,7 +407,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) break; case 'dateTime.tz': $propertyType = Properties::PROPERTY_TYPE_DATE; - $propertyValue = strtotime(trim($propertyValue)); + $propertyValue = strtotime(trim((string) $propertyValue)); break; } @@ -420,8 +420,9 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) $worksheetID = 0; $xml_ss = $xml->children($namespaces['ss']); - foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = $worksheet->attributes($namespaces['ss']); + foreach ($xml_ss->Worksheet as $worksheetx) { + $worksheet = ($worksheetx === null) ? new SimpleXMLElement('') : $worksheetx; + $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); if ( (isset($this->loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && @@ -444,7 +445,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) // locally scoped defined names if (isset($worksheet->Names[0])) { foreach ($worksheet->Names[0] as $definedName) { - $definedName_ss = $definedName->attributes($namespaces['ss']); + $definedName_ss = self::getAttributes($definedName, $namespaces['ss']); $name = (string) $definedName_ss['Name']; $definedValue = (string) $definedName_ss['RefersTo']; $convertedValue = AddressHelper::convertFormulaToA1($definedValue); @@ -458,7 +459,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) $columnID = 'A'; if (isset($worksheet->Table->Column)) { foreach ($worksheet->Table->Column as $columnData) { - $columnData_ss = $columnData->attributes($namespaces['ss']); + $columnData_ss = self::getAttributes($columnData, $namespaces['ss']); if (isset($columnData_ss['Index'])) { $columnID = Coordinate::stringFromColumnIndex((int) $columnData_ss['Index']); } @@ -475,14 +476,14 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) $additionalMergedCells = 0; foreach ($worksheet->Table->Row as $rowData) { $rowHasData = false; - $row_ss = $rowData->attributes($namespaces['ss']); + $row_ss = self::getAttributes($rowData, $namespaces['ss']); if (isset($row_ss['Index'])) { $rowID = (int) $row_ss['Index']; } $columnID = 'A'; foreach ($rowData->Cell as $cell) { - $cell_ss = $cell->attributes($namespaces['ss']); + $cell_ss = self::getAttributes($cell, $namespaces['ss']); if (isset($cell_ss['Index'])) { $columnID = Coordinate::stringFromColumnIndex((int) $cell_ss['Index']); } @@ -524,7 +525,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) $cellData = $cell->Data; $cellValue = (string) $cellData; $type = DataType::TYPE_NULL; - $cellData_ss = $cellData->attributes($namespaces['ss']); + $cellData_ss = self::getAttributes($cellData, $namespaces['ss']); if (isset($cellData_ss['Type'])) { $cellDataType = $cellData_ss['Type']; switch ($cellDataType) { @@ -587,7 +588,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) $author = (string) $commentAttributes->Author; } $node = $cell->Comment->Data->asXML(); - $annotation = strip_tags($node); + $annotation = strip_tags((string) $node); $spreadsheet->getActiveSheet()->getComment($columnID . $rowID)->setAuthor($author)->setText($this->parseRichText($annotation)); } @@ -610,7 +611,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) if ($rowHasData) { if (isset($row_ss['Height'])) { $rowHeight = $row_ss['Height']; - $spreadsheet->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); + $spreadsheet->getActiveSheet()->getRowDimension($rowID)->setRowHeight((float) $rowHeight); } } @@ -631,7 +632,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) $activeWorksheet = $spreadsheet->setActiveSheetIndex(0); if (isset($xml->Names[0])) { foreach ($xml->Names[0] as $definedName) { - $definedName_ss = $definedName->attributes($namespaces['ss']); + $definedName_ss = self::getAttributes($definedName, $namespaces['ss']); $name = (string) $definedName_ss['Name']; $definedValue = (string) $definedName_ss['RefersTo']; $convertedValue = AddressHelper::convertFormulaToA1($definedValue); @@ -662,10 +663,11 @@ private function parseStyles(SimpleXMLElement $xml, array $namespaces): void } foreach ($xml->Styles[0] as $style) { - $style_ss = $style->attributes($namespaces['ss']); + $style_ss = self::getAttributes($style, $namespaces['ss']); $styleID = (string) $style_ss['ID']; $this->styles[$styleID] = (isset($this->styles['Default'])) ? $this->styles['Default'] : []; - foreach ($style as $styleType => $styleData) { + foreach ($style as $styleType => $styleDatax) { + $styleData = $styleDatax ?? new SimpleXMLElement(''); $styleAttributes = $styleData->attributes($namespaces['ss']); switch ($styleType) { case 'Alignment': @@ -750,15 +752,16 @@ private function parseStyleBorders($styleID, SimpleXMLElement $styleData, array $diagonalDirection = ''; $borderPosition = ''; foreach ($styleData->Border as $borderStyle) { - $borderAttributes = $borderStyle->attributes($namespaces['ss']); + $borderAttributes = self::getAttributes($borderStyle, $namespaces['ss']); $thisBorder = []; $style = (string) $borderAttributes->Weight; $style .= strtolower((string) $borderAttributes->LineStyle); $thisBorder['borderStyle'] = self::$mappings['borderStyle'][$style] ?? Border::BORDER_NONE; - foreach ($borderAttributes as $borderStyleKey => $borderStyleValue) { + foreach ($borderAttributes as $borderStyleKey => $borderStyleValuex) { + $borderStyleValue = (string) $borderStyleValuex; switch ($borderStyleKey) { case 'Position': - $borderStyleValue = strtolower((string) $borderStyleValue); + $borderStyleValue = strtolower($borderStyleValue); if (in_array($borderStyleValue, self::$borderPositions)) { $borderPosition = $borderStyleValue; } elseif ($borderStyleValue == 'diagonalleft') { @@ -784,6 +787,11 @@ private function parseStyleBorders($styleID, SimpleXMLElement $styleData, array } } + private static function getAttributes(?SimpleXMLElement $simple, string $node): SimpleXMLElement + { + return ($simple === null) ? new SimpleXMLElement('') : ($simple->attributes($node) ?? new SimpleXMLElement('')); + } + private static $underlineStyles = [ Font::UNDERLINE_NONE, Font::UNDERLINE_DOUBLE, @@ -854,7 +862,8 @@ private function parseStyleFont(string $styleID, SimpleXMLElement $styleAttribut */ private function parseStyleInterior($styleID, SimpleXMLElement $styleAttributes): void { - foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { + foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValuex) { + $styleAttributeValue = (string) $styleAttributeValuex; switch ($styleAttributeKey) { case 'Color': $this->styles[$styleID]['fill']['endColor']['rgb'] = substr($styleAttributeValue, 1);