Ошибка в переменной с тегами XML при разборе файлов ODT

Я внедряю TinyButStrong / OpenTBS в системе, которая должна обрабатывать документы ODT, и столкнулся с проблемой, связанной с конкретным шаблоном, в котором есть теги внутри имени переменной.

Ситуация выглядит следующим образом:

Часть шаблона:

введите описание изображения здесь

Соответствующая часть content.xml

<table:table-cell table:style-name="Table3.A1" office:value-type="string">
<text:p text:style-name="P22">Tipo de documento</text:p>
<text:p text:style-name="P29">
<text:span text:style-name="T7">
[b.</text:span>tipoDocumento<text:span text:style-name="T7">]
</text:span>
</text:p>
</table:table-cell>

Как видите, имя переменной </text:span>tipoDocumento<text:span text:style-name="T7">, Документ был отредактирован в LibreOffice, и по неизвестной причине теги были добавлены.

Я думал, что смогу передать полное имя переменной (с включенными тегами), и OpenTBS правильно проанализирует значение, поэтому я попробовал следующее:

$data = ['</text:span>tipoDocumento<text:span text:style-name="T7">' => 'somevalue'];
$tbs = new clsTinyButStrong;
$tbs->Plugin(TBS_INSTALL, OPENTBS_PLUGIN);
$tbs->LoadTemplate($templatePath, OPENTBS_ALREADY_UTF8);
// Note that we need to send an array of arrays to $data,
$tbs->MergeBlock($block, 'array', [$data]);

Но это приводит к ошибке TBS:

<b>TinyButStrong Error</b> in field &#91;b.</text:span>tipoDocumento<text:span text:style-name...]: item '&lt;/text:span&gt;tipoDocumento&lt;text:span text:style-name' is not an existing key in the array. <em>This message can be cancelled using parameter 'noerr'.</em>

Я сделал некоторые отладки и понял, что в основе tbs_class.phpстрока 1177 (в meth_Locator_Replace(), где выдается ошибка), содержание $Loc->SubLst[$i] является </text:span>tipoDocumento<text:span text:style-name, который не соответствует значению в моем массиве.

Итак, я предполагаю, что по какой-то причине TBS разрывает индекс знаком равенства (=), что вызывает эту проблему. Так,

  1. Это специально?
  2. Можно ли это исправить (в случае ошибки), чтобы разрешить теги с одинаковыми знаками?
  3. Есть ли лучший способ избежать тегов в variablesor, есть ли способ избежать этого в LibreOffice?

1

Решение

Строка </text:span>tipoDocumento<text:span text:style-name="T7"> не может быть именем поля в TBS. Это потому, что пробел, символ равенства, точка и точка с запятой и некоторые другие являются специальными символами для полей TBS.

Такое внутреннее содержимое XML может быть автоматически добавлено в LibreOffice (или даже в Ms Office), когда вы изменили форматирование или когда есть информация об орфографии.

Решение состоит в том, чтобы выбрать поле TBS в LibreOffice, затем вырезать его, а затем паста без форматирования. Тогда весь внутренний XML должен был исчезнуть, или, по крайней мере, он ограничивает текст, не разрезая его.

1

Другие решения

@ Skrol29ответ является наиболее надежным решением.

Однако одна из причин, по которой мы используем шаблоны, заключается в том, что конечные пользователи могут их редактировать, и им будет нелегко объяснить, зачем им это нужно, поскольку в LibreOffice (или в Microsoft Office нет визуальных изменений). в этом отношении).

Итак, я закончил синтаксический анализ источника шаблона перед его сохранением, тем самым удалив все теги XML из переменных.

Это код, который я использую при загрузке нового файла шаблона:

// Create a temporary file, only to load it with TBS
// $fileContents is the binary file contents and $extensao is the file extension
$filePath = intranet_storage_path(sha1($fileContents) . '.' . $extensao, 'tmp');
// Store the binary contents in the file path
file_put_contents($filePath, $fileContents);

// Create a new TBS instance and load OpenTBS
$tbs = new clsTinyButStrong;
$tbs->Plugin(TBS_INSTALL, OPENTBS_PLUGIN);

// Load the temporary file
$tbs->LoadTemplate($filePath, OPENTBS_ALREADY_UTF8);

// Find all variables (the only block name is 'b')
preg_match_all(
"/(\[b\.  # Start by finding a part of [ followed by the block name and a dot
[^.\];]+  # Now we should get all characters until one of the following is found: `.` (dot), `]`, `;
[\]|;]    # Stop the regex when a `]` or `;` is found.
)/ix",
$tbs->Source,
$matches
);

// Loop through all the found variables
$searched = $replaced = [];
foreach ($matches[0] as $var) {
// Fill the $searched and $replaced where $searched is the real variable name
// with XML tags (if they exist) and $replaced is the variable without tags
$searched[] = $var;
$replaced[] = strip_tags($var);
}

// Replace the contents of the Source
$tbs->Source = str_replace($searched, $replaced, $tbs->Source);

// Store the final template file with variables without XML
$tbs->Show(OPENTBS_FILE, $filePath);

Я должен заявить, что это решение приведет к неверному XML, если в переменной есть только открытый или закрытый тег. Следующие примеры нарушат XML (и вы не сможете открыть или проанализировать документ):

<text:span text:style-name="T7">[b.tipoDocumento<text:span text:style-name="T7">]</text:span>
// OR
<text:span text:style-name="T7">[b.</text:span>tipoDocumento]</text:span>

Однако из тестовых случаев, которые у меня были, всегда есть открывающий и закрывающий тег (как представлено в вопросе), поэтому удаление их приведет к правильному XML.

0

По вопросам рекламы [email protected]