Avemey / zexmlss

ZEXMLSS Lazarus/Delphi component for read/write ods, excel xml, xlsx
http://avemey.com/zexmlss/index.php
Other
70 stars 52 forks source link

XMLSS: HTML Cells corruption #5

Open the-Arioch opened 10 years ago

the-Arioch commented 10 years ago

Берём ячейку со значением, внутри которого разные шрифты, надстрочные и подстрочные индексы, типа

  <Cell ss:StyleID="s80">
   <ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
   <I>
    <Font html:Color="#000000">L</Font> 
   <Sub>
    <Font html:Color="#000000">0</Font> 
    </Sub>
    <Font html:Color="#000000">– долгота осевого меридиана шестиградусной зоны [градусы];</Font> 
    </I>
    </ss:Data>
    </Cell>

Или

   <Cell ss:StyleID="s70">
   <ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
   <I>
   <Font html:Color="#000000">В – геодезическая широта рассматриваемого объекта</Font> 
     <Font html:Color="#FF0000">[радианы]</Font> 
     <Font html:Color="#000000">;</Font> 
     </I>
     </ss:Data>
     </Cell>

Открываем в компоненте, закрываем.... и не можем открыть в Экселе:

Ошибка XML в "Таблица" Причина: Слишком много тегов Файл: C:\xxxx.xml Группа: Font Тег: Font Атрибут: Color Значение: #000000

Вглядываемся - и находим там такие, ставшие вложенными структуры:

  <Cell ss:StyleID="s27">
  <ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
  <Font html:Color="#FF0000">
    <Font html:Color="#000000">В – геодезическая широта рассматриваемого объекта</Font> 
    [радианы] 
    </Font>
    <Font html:Color="#000000">;</Font> 
    <I /> 
    </ss:Data>
    </Cell>

    <Cell ss:StyleID="s37">
     <ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
     <Sub>
     <Font html:Color="#000000">
      <Font html:Color="#000000">L</Font> 
      0 
      </Font>
      </Sub>
      <Font html:Color="#000000">– долгота осевого меридиана шестиградусной зоны [градусы];</Font> 
      <I /> 
      </ss:Data>
      </Cell>
the-Arioch commented 10 years ago
ProcessedCell.Data ==

'<I><Font html:Color="#000000">В – геодезическая  широта рассматриваемого объекта </Font>'+
'<Font'#$D#$A'html:Color="#FF0000">[радианы]</Font><Font html:Color="#000000">;</Font></I>'

в zexmlssutils, WritePage перед CorrectStrForXML, а после -

'<Font html:Color="#000000"><Font'#$D#$A'        html:Color="#FF0000">'+
'<Font html:Color="#000000">В – геодезическая  широта рассматриваемого объекта '+
'</Font>[радианы]</Font>;</Font><I></I>'
the-Arioch commented 10 years ago
             if Stack[kol].TagName = Stack[kol-1].TagName then
             begin
               dec(t);
               if t <> 1 then
                 Corrected := Stack[kol-1].TextBeforeTag + Stack[kol-1].RawTag + Corrected +
                              Stack[kol].TextBeforeTag + Stack[kol].RawTag
               else
                 Corrected := Corrected + Stack[kol-1].TextBeforeTag + Stack[kol-1].RawTag +
                              Stack[kol].TextBeforeTag + Stack[kol].RawTag;
               dec(t);

в районе 890-й строки у тебя безумие какое-то.

Во-первых, T - это копия KOL; Это длина стека, она же вложенность тегов. Т.е. не нужна. Во-вторых, она намеренно убивает все тэги, кроме корневых.

Т.е. вариант THEN просто никогда не должен выполняться


Вообще непонятно, что ты пытаешься добиться со стеком. Только проверить согласованность? Принудительно закрыть забытые теги ? Непонятно.

the-Arioch commented 10 years ago

https://github.com/the-Arioch/avemey.com/commit/e8acaf3108e1c0f36d444d054396107b17a4ee2a#diff-c92165e1365b067ebcfe41fe9eb097fb https://github.com/the-Arioch/avemey.com/commit/8c58c9d9af9dad8c13f5704a52d774e1664dc20a

http://pastebin.com/3K1Pii9W http://pastebin.com/2uLQEUY3

Avemey commented 10 years ago

Подправлено: 68ea450a664db542ce2c4b6b554f2dc96c1b2a75

T не есть копия KOL! T - кол-во валидных (непокоцанных) тэгов! Заведено на случай, если в текст ячейки кто-то попытается записать что-то вроде этого: " <font bla-bla-bla".

the-Arioch commented 10 years ago

Думаю, надо готовить тест-кейсы, иначе получается тришкин кафтан.

И я таки не смог придумать входную строку, при которой T и KOL рассинхронизируются. Зато перегрузка Corrected разными задачами привела к порче валидного значения :-(

... И как всегда это вскрывать в самый неподходящий момент.

Ps. А у тебя D7 стоит? Разве можно объявлять типы внутри процедур? D5 точно не дала бы

Avemey notifications@github.com написал(а):

Подправлено: 68ea450a664db542ce2c4b6b554f2dc96c1b2a75

T не есть копия KOL! T - кол-во валидных (непокоцанных) тэгов! Заведено на случай, если в текст ячейки кто-то попытается записать что-то вроде этого: " <font bla-bla-bla".


Reply to this email directly or view it on GitHub: https://github.com/Avemey/zexmlss/issues/5#issuecomment-27642901

Отправлено через К-9 Mail. Извините за краткость, пожалуйста.

the-Arioch commented 10 years ago

Что за magic value t=1? Почему не 3,0,-1?

Ты уверен, что stack(kol-2) существует?

PS: интересно, что делает setlength(--). Не получается ли, что мы фрагментируем кучу и копируем туда-сюда-обратно? Мне вот чисто субъективно хочется длинную только увеличивать, причем большими порциями, как tlist

Avemey notifications@github.com написал(а):

Подправлено: 68ea450a664db542ce2c4b6b554f2dc96c1b2a75

T не есть копия KOL! T - кол-во валидных (непокоцанных) тэгов! Заведено на случай, если в текст ячейки кто-то попытается записать что-то вроде этого: " <font bla-bla-bla".


Reply to this email directly or view it on GitHub: https://github.com/Avemey/zexmlss/issues/5#issuecomment-27642901

Отправлено через К-9 Mail. Извините за краткость, пожалуйста.

the-Arioch commented 10 years ago

И это, второй кормит тоже посмотри

Avemey notifications@github.com написал(а):

Подправлено: 68ea450a664db542ce2c4b6b554f2dc96c1b2a75

T не есть копия KOL! T - кол-во валидных (непокоцанных) тэгов! Заведено на случай, если в текст ячейки кто-то попытается записать что-то вроде этого: " <font bla-bla-bla".


Reply to this email directly or view it on GitHub: https://github.com/Avemey/zexmlss/issues/5#issuecomment-27642901

Отправлено через К-9 Mail. Извините за краткость, пожалуйста.

Avemey commented 10 years ago

В теории, stack[kol-2] должен существовать, т.к. данная проверка ведётся только для закрывающих тэгов (kol >= 2 (0, 1, 2)) и при t <> 1 (можно было бы написать t > 1). Пока не найден контрпример, будем считать что так оно и есть.

В 7-ой (да вроде и в 6-ой тоже) типы можно объявлять в процедурах.

Если есть примеры хитрого оформления ячеек, которое поломает сохранение, буду пересматиривать алгоритм.

the-Arioch commented 10 years ago

Ты мой тестовый файл гонял, по ссылке? Я тут на мобиле с edge gprs, так что внимательно посмотреть не могу. Более того, я не вижу примеров что и как ты собираешься исправлять. Например очевидное закрытие промежуточных забытых тегов ты и то не делаешь. Но тогда - что?

Но чисто из здравого смысла, тезисно:

  1. Html по структура с произвольным (заранее неизвестным) количеством вложений и повторов тегов (тег == открытие + внутренность + закрытие)
  2. Таким и должен быть жизненный цикл конечного автомата: открытие - внутренность - закрытие.
  3. Кроме проверок "стек пуст" и "очередь ввода пуста" все остальные проверки должны быть локальными внутри текущего тэга. Так можно сделать минимальный общий код, не провалилась в комбинаторный перебор исключений.
  4. T=1 - это именно такое исключение (а почему не 3,5,7...? Не 0?)
  5. "по правильному", в лоб, каждый новый тэг(т. е. открытие) надо начинать создавая новый "чистый" автомат. В рамках данного кода это означает рекурсивно вызвать процедуру. ( и вероятно передать ей десяток парамеиров)
  6. Ты развернул рекурсию в цикл, а создание нового автомата имитируешь зачисткой его состояния до "нулевого" (с сохранением важного состояния на стеке).
  7. Но тогда зачищать надо ВСЁ состояние автомата полностью, включая переменную Corrected. И зачистка должна выполняться вместо создания нового автомата, т. Е. При открытии тэга. А не при закрытии (при закрытии надо удалять автомат, т. Е. Мёржить его состояние с восстанавливаемым со стека). При этом не имея списка что и как должна функция исправлять, я не могу проверить, что разные _badtag при этом не ломаются.
  8. Чисто формально corrected - внешняя переменная, но по функционалу она - часть локального состояния автомата при разборе конкретного тега, так же как например локальная s.
  9. Да, это значит, что corrected перегружена. По хорошему функции локального состояния и возврата значения лучше бы разделить по разным переменным.
  10. При вложенных тегах t всегда равно или kol или kol+1. Т. Е. менять <>1 на >1 нельзя.
  11. Посмотри второй коммит по ссылке, у тебя проблемы с курсивом в xml

Отправлено через К-9 Mail. Извините за краткость, пожалуйста.

the-Arioch commented 10 years ago

что-то вроде этого: " bla-bla-bla".

Это гитхаб, он ненавидит xml. Пример не дошёл :-D

Отправлено через К-9 Mail. Извините за краткость, пожалуйста.

the-Arioch commented 10 years ago

Да, ещё. После этого разбора идёт цикл по остатки стека, но почему-то в вывернутом порядке, от старых элементов к новым. При этом corrected, которое будет накапливаться после уложенных на стек элементов, добавляется не справа, а слева. Правда у меня этот цикл ни разу не выполнился. Так что я не вполне понимаю при каких условиях и что он восстанавливает. Опять же не хватает примеров...

Отправлено через К-9 Mail. Извините за краткость, пожалуйста.