使用OpenTBS读取ODS文件时单元格换行内容丢失问题求助
解决ODS单元格多行文本读取截断问题(TinyButStrong+OpenTBS)
ODS格式中,单元格内的多行文本是通过多个<text:p>标签存储的,OpenTBS默认只会提取第一个<text:p>的内容,这就是你遇到内容截断的原因。以下是两种可行的解决方法:
方法1:利用OpenTBS的回调函数提前处理
通过OnXmlParsing回调在解析XML阶段直接拼接单元格内的所有<text:p>内容,确保后续获取的数据是完整的:
require_once('tinybutstrong/tbs_class.php'); require_once('opentbs/opentbs_class.php'); $TBS = new clsTinyButStrong; $OpenTBS = new clsOpenTBS; // 注册XML解析回调,处理多行单元格 $OpenTBS->OnXmlParsing = function($Node, $Path, $RecData) { // 匹配ODS单元格的text:p节点路径 if ($Path === 'office:document-content/office:body/office:spreadsheet/table:table/table:table-row/table:table-cell/text:p') { $cell_node = $Node->parentNode; $text_p_list = $cell_node->getElementsByTagName('text:p'); $full_content = ''; foreach ($text_p_list as $p_node) { $text = trim($p_node->textContent); if (!empty($full_content)) { $full_content .= "\n"; } $full_content .= $text; } // 替换当前节点内容为拼接后的完整文本 $Node->nodeValue = $full_content; } return $RecData; }; // 加载目标ODS文件 $OpenTBS->LoadTemplate('inferno.ods'); // 获取第一个表格的数据(可根据实际表格位置调整索引) $sheet_data = $OpenTBS->GetSourcePart('//table:table[1]'); // 转换为PHP数组 $result_array = []; foreach ($sheet_data->children() as $row_node) { $row = []; foreach ($row_node->children() as $cell_node) { // 直接取处理后的单元格文本 $row[] = $cell_node->textContent; } $result_array[] = $row; } print_r($result_array);
方法2:手动遍历XML节点处理
如果回调方式不适用,也可以直接解析XML内容,手动遍历单元格内的所有<text:p>标签拼接内容:
require_once('tinybutstrong/tbs_class.php'); require_once('opentbs/opentbs_class.php'); $TBS = new clsTinyButStrong; $OpenTBS = new clsOpenTBS; $OpenTBS->LoadTemplate('inferno.ods'); // 获取原始XML内容 $xml_content = $TBS->Source; $xml = simplexml_load_string($xml_content); // 注册ODS所需的XML命名空间 $xml->registerXPathNamespace('office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); $xml->registerXPathNamespace('table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'); $xml->registerXPathNamespace('text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); // 遍历所有行和单元格 $result_array = []; $rows = $xml->xpath('//table:table-row'); foreach ($rows as $row) { $cells = $row->xpath('./table:table-cell'); $row_data = []; foreach ($cells as $cell) { $p_tags = $cell->xpath('./text:p'); $cell_text = ''; foreach ($p_tags as $p) { $text = trim((string)$p); if (!empty($cell_text)) { $cell_text .= "\n"; } $cell_text .= $text; } $row_data[] = $cell_text; } $result_array[] = $row_data; } print_r($result_array);
关键注意点
- ODS的XML使用了命名空间,必须通过
registerXPathNamespace注册对应命名空间才能正确定位节点,这是很多人用SimpleXML解析失败的核心原因。 - 拼接时可以根据需求选择换行符(
\n或\r\n),或者用其他分隔符。
内容的提问来源于stack exchange,提问作者sariDon
相关产品推荐
相关产品推荐

