Форум программистов, компьютерный форум, киберфорум
diadiavova
Войти
Регистрация
Восстановить пароль
Оценить эту запись

Об XML-фильтрах OpenOffice. Часть 3-я.

Запись от diadiavova размещена 10.06.2015 в 12:25
Обновил(-а) diadiavova 12.04.2016 в 15:29
Метки libreoffice, openoffice, xslt

  1. Решение проблемы разделения на строки.
  2. Демонстрация работы подсветки синтаксиса кода
Решение проблемы разделения на строки.

Коль скоро мы начали с определения цвета, возьмемся за раскрашивание текста. То есть целью будет получение текста документа, раскрашенного с помощью BB-кодов. Добавим в преобразование следующую функцию, которая будет оборачивать переданный узел тегами COLOR
XML
1
2
3
4
5
  <xsl:function name="my:colorize">
    <xsl:param name="node"/>
    <xsl:variable name="color" select="my:style-property-value($node, 'fo:color')"/>
    <xsl:value-of select="concat('[COLOR=&quot;', $color, '&quot;]', $node, '[/COLOR]')"/>
  </xsl:function>
Кроме того, нам понадобится шаблон, обрабатывающий текстовые узлы, а так же отредактируем шаблон, с которого начинается обработка документа
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  <xsl:template match="/">
    <root>
      <xsl:text disable-output-escaping="yes">
&lt;![CDATA[
</xsl:text>
 
      <xsl:apply-templates select="//office:body"/>  
 
      <xsl:text disable-output-escaping="yes">
]]&gt;
</xsl:text>
    </root>
  </xsl:template>
 
 
  <xsl:template match="text()">
    <xsl:value-of select="my:colorize(.)" disable-output-escaping="yes"/>
  </xsl:template>
 
<xsl:template match="office:binary-data"/>
Кроме того добавил <xsl:template match="office:binary-data"/>, чтобы исключить бинарные данные из выходного потока.

Вот результат
XML
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<root>
<![CDATA[
[COLOR="#2e74b5"]Заголовок 1[/COLOR]Обычный текст[COLOR="#2e74b5"]Заголовок 2[/COLOR][COLOR="#1f4d78"]Заголовок 3[/COLOR][COLOR="#2e74b5"]Заголовок 4[/COLOR][COLOR="#2e74b5"]Заголовок 5[/COLOR][COLOR="#1f4d78"]Заголовок 6[/COLOR][COLOR="#1f4d78"]Заголовок 7[/COLOR]Название[COLOR="#5a5a5a"]Подзаголовок[/COLOR][COLOR="#5b9bd5"]Сильное выделение[/COLOR]Строгий[COLOR="#404040"]Цитата 2[/COLOR][COLOR="#5a5a5a"]Слабая ссылка[/COLOR][COLOR="#5b9bd5"]Сильная ссылка[/COLOR]Название книгиАбзац списка.ЖирныйКурисивПодчеркнутыйПеречекнутыйХНижний индексХВерхний идексКрупный шрифт 72Мелкий шрифт 8Левое выравниваниеВыравнивание по центруПравое выравниваниеПервый пункт маркированного спискаВторой пункт маркированного спискаПервый пункт нумерованного спискаПункт 1.a;alfjasdf; lj l ;l lj ;lk lkj;lkj l sdls dfslkj as;lПункт 1.b b xj 'nj pf [eqyz&amp;Второй пункт нумерованного списка[COLOR="#ff0000"]Текст красного цвета[/COLOR][COLOR="#00b0f0"]Текст синего цвета[/COLOR]Выделение желтым/*Далее таблица*/1.11.21.31.41.22.22.32.43.13.23.33.4[COLOR="#0563c1"]Ссылка на гуголь[/COLOR]/*Далее картинка*/ЗакладкаТекст с отступом 2 смСсылка на сноску1Сноска на странице.
]]>
</root>
Если текстовые данные просто вставить в пост как цитату, получится вот что
Цитата:
Заголовок 1Обычный текстЗаголовок 2Заголовок 3Заголовок 4Заголовок 5Заголовок 6Заголовок 7НазваниеПодзаголовокСильное выделениеСтрогийЦитата 2Слабая ссылкаСильная ссылкаНазвание книгиАбзац списка.ЖирныйКурисивПодчеркнутыйПеречекнутыйХНижний индексХВерхний идексКрупный шрифт 72Мелкий шрифт 8Левое выравниваниеВыравнивание по центруПравое выравниваниеПервый пункт маркированного спискаВторой пункт маркированного спискаПервый пункт нумерованного спискаПункт 1.a;alfjasdf; lj l ;l lj ;lk lkj;lkj l sdls dfslkj as;lПункт 1.b b xj 'nj pf [eqyz&amp;Второй пункт нумерованного спискаТекст красного цветаТекст синего цветаВыделение желтым/*Далее таблица*/1.11.21.31.41.22.22.32.43.13.23.33.4Ссылка на гуголь/*Далее картинка*/ЗакладкаТекст с отступом 2 смСсылка на сноску1Сноска на странице.
Приятно, конечно, что все раскрасилось как в оригинальном документе, но там вроде как текст многострочным был. А это еще что такое? Так здесь еще строки отрезаются по ширине страницы, а в коде все вообще в одну строку сложено.

Если взглянуть на фрагменты кода с текстом, которые мы уже рассмотрели ранее, то можно заметить, что среди форматирующих элементов (тех, которые имеют ссылку на стиль) на верхнем уровне оказывается либо text:p (для обычного текста) либо text:h (для заголовков). Нетрудно догадаться, что назначение этих элементов примерно такое же, как у элементов p и h1-h6 в HTML. То есть иными словами, мы видим, что любой текст "упакован" в блочный элемент, внутри которого дополнительно могут находиться инлайновые форматирующие элементы. Конечно, это несколько упрощенный взгляд, но если принять во внимание только это обстоятельство, можно получить гораздо более адекватный результат.
Добавим в преобразование такой шаблон
XML
1
2
3
4
5
  <xsl:template match="text:h|text:p">
    <xsl:apply-templates/>
        <xsl:text>
  </xsl:text>
  </xsl:template>
И получим куда более удовлетворительный результат.
Кликните здесь для просмотра всего текста
Цитата:
Заголовок 1
Обычный текст
Заголовок 2
Заголовок 3
Заголовок 4

Заголовок 5
Заголовок 6
Заголовок 7
Название
Подзаголовок
Сильное выделение
Строгий
Цитата 2
Слабая ссылка
Сильная ссылка

Название книги
Абзац списка.
Жирный
Курисив
Подчеркнутый
Перечекнутый
ХНижний индекс
ХВерхний идекс
Крупный шрифт 72
Мелкий шрифт 8
Левое выравнивание
Выравнивание по центру
Правое выравнивание
Первый пункт маркированного списка
Второй пункт маркированного списка

Первый пункт нумерованного списка
Пункт 1.a;alfjasdf; lj l ;l lj ;lk lkj;lkj l sdls dfslkj as;l
Пункт 1.b b xj 'nj pf [eqyz&amp;
Второй пункт нумерованного списка

Текст красного цвета
Текст синего цвета
Выделение желтым
/*Далее таблица*/
1.1
1.2
1.3
1.4
1.2
2.2
2.3
2.4
3.1
3.2
3.3
3.4

Ссылка на гуголь

/*Далее картинка*/

Закладка
Текст с отступом 2 см
Ссылка на сноску1Сноска на странице
.
Следует обратить внимание еще на пару обстоятельств. Все текстовые узлы в документе имеют нормализованную форму. То есть там нет текстов, которые содержат более одного пробела подряд или переходы на новые строки. Однако в документе такие места есть, поэтому интересно посмотреть, как это решается в коде документа. Вот так выглядит код элемента с разрывом строки
XML
1
<text:span text:style-name="T16">1.a;alfjasdf; lj l ;l lj ;lk <text:line-break/>lkj;lkj l sdls dfslkj as;l</text:span>
Здесь элемент text:line-break по сути выполняет ту же роль, что и элемент br в HTML. Если кто не в курсе, то с клавиатуры это набирается путем ввода сочетания Shift+Enter. В этом случае новый абзац не создается, а просто обрывается строка. Другой случай - несколько пробелов подряд. В документе это тоже имеется, но приведу более чистый код
XML
1
<text:p text:style-name="P8">Текст до десяти пробелов <text:s text:c="9"/>Текст после десяти пробелов</text:p>
Думаю, пояснения не нужны. Добавляем еще два шаблона
XML
1
2
3
4
5
6
7
8
9
[noparse]
  <xsl:template match="text:s">
  <xsl:value-of select="for $s in (1 to @text:c) return ' '"/>
    </xsl:template>
  <xsl:template match="text:line-break">
        <xsl:text>
  </xsl:text>
  </xsl:template>
[/noparse]
Вот что имеем теперь
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="UTF-8"?>
<root>
<![CDATA[
[COLOR="#2e74b5"]Заголовок 1[/COLOR]
Обычный текст
[COLOR="#2e74b5"]Заголовок 2[/COLOR]
[COLOR="#1f4d78"]Заголовок 3[/COLOR]
[COLOR="#2e74b5"]Заголовок 4[/COLOR]
 
[COLOR="#2e74b5"]Заголовок 5[/COLOR]
[COLOR="#1f4d78"]Заголовок 6[/COLOR]
[COLOR="#1f4d78"]Заголовок 7[/COLOR]
Название
[COLOR="#5a5a5a"]Подзаголовок[/COLOR]
[COLOR="#5b9bd5"]Сильное выделение[/COLOR]
Строгий
[COLOR="#404040"]Цитата 2[/COLOR]
[COLOR="#5a5a5a"]Слабая ссылка[/COLOR]
[COLOR="#5b9bd5"]Сильная ссылка[/COLOR]
 
Название книги
Абзац списка.
Жирный
Курисив
Подчеркнутый
Перечекнутый
ХНижний индекс
ХВерхний идекс
Крупный шрифт 72
Мелкий шрифт 8
Левое выравнивание
Выравнивание по центру
Правое выравнивание
Первый пункт маркированного списка
Второй пункт маркированного списка
 
Первый пункт                                                                                                           нумерованного списка
Пункт 1.a;alfjasdf; lj l ;l lj ;lk 
lkj;lkj l sdls dfslkj as;l
Пункт 1.b b xj 'nj pf [eqyz&amp;
Второй пункт нумерованного списка
Текст до десяти пробелов                  Текст после десяти пробелов
[COLOR="#ff0000"]Текст красного цвета[/COLOR]
[COLOR="#00b0f0"]Текст синего цвета[/COLOR]
Выделение желтым
/*Далее таблица*/
1.1
1.2
1.3
1.4
1.2
2.2
2.3
2.4
3.1
3.2
3.3
3.4
 
[COLOR="#0563c1"]Ссылка на гуголь[/COLOR]
 
/*Далее картинка*/
 
Закладка
Текст с отступом 2 см
Ссылка на сноску1Сноска на странице
.
 
 
]]>
</root>

На самом деле дело не ограничивается только именами элементов. Конечно на способ отображения влияет и стиль и контекст. Если говорить о стилях, то у них есть такой атрибут, как style:family. Если он имеет значение paragraph, то элементы, к которым этот стиль относится видимо и будут блочными. Хотя, как видно даже из приведенного примера элементы такого типа вовсе не всегда должны обрабатываться одинаково. Например содержимое ячейки таблицы тоже включает text:p, но если мы будем каждую ячейку на новой строке размещать, то таблицы в BB-кодах уже не получится. Но это я уже вперед забежал. Пока нам достаточно того, что уже сделано.

Демонстрация работы подсветки синтаксиса кода

Ну, о чем-то реально полезном пока говорить рановато, но то, что мы уже сделали вполне можно посмотреть в работе. На данный момент наше преобразование имеет вид как во вложении (ColorizeTextOOFilter.zip).
Можно сохранить его в папке для фильтров и в дальнейшем использовать для тестов, предварительно добавив как фильтр в программу Writer. В Visual Studio имеется одна интересная особенность: когда из редактора кода копируется код, то в буфере обмена он сохраняется не только как текст, но и в формате RTF. Таким образом, когда он вставляется в программу, поддерживающую этот формат, то сохраняется подсветка синтаксиса. "Офисные" программы RTF поддерживают, а нам как раз интересно посмотреть на подсветку синтаксиса. Таким образом я скопирую часть кода нашего преобразования из студии, вставлю код в поле редактора и сохраню с помощью нашего фильтра.
Результат у меня получился вот такой
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<root>
<![CDATA[
   [COLOR="#0000ff"]<[/COLOR][COLOR="#2b91af"]xsl:template[/COLOR][COLOR="#0000ff"] [/COLOR][COLOR="#ff0000"]match[/COLOR][COLOR="#0000ff"]=[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]/[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]>[/COLOR]
       [COLOR="#0000ff"]<[/COLOR][COLOR="#a31515"]root[/COLOR][COLOR="#0000ff"]>[/COLOR]
           [COLOR="#0000ff"]<[/COLOR][COLOR="#2b91af"]xsl:text[/COLOR][COLOR="#0000ff"] [/COLOR][COLOR="#ff0000"]disable-output-escaping[/COLOR][COLOR="#0000ff"]=[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]yes[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]>[/COLOR]
[COLOR="#ff0000"]&lt;[/COLOR][COLOR="#000000"]![CDATA[[/COLOR]
[COLOR="#0000ff"]</[/COLOR][COLOR="#2b91af"]xsl:text[/COLOR][COLOR="#0000ff"]>[/COLOR]
 
           [COLOR="#0000ff"]<[/COLOR][COLOR="#2b91af"]xsl:apply-templates[/COLOR][COLOR="#0000ff"] [/COLOR][COLOR="#ff0000"]select[/COLOR][COLOR="#0000ff"]=[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]//office:body[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]/> [/COLOR]         
 
           [COLOR="#0000ff"]<[/COLOR][COLOR="#2b91af"]xsl:text[/COLOR][COLOR="#0000ff"] [/COLOR][COLOR="#ff0000"]disable-output-escaping[/COLOR][COLOR="#0000ff"]=[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]yes[/COLOR][COLOR="#000000"]"[/COLOR][COLOR="#0000ff"]>[/COLOR]
[COLOR="#000000"]]][/COLOR][COLOR="#ff0000"]&gt;[/COLOR]
[COLOR="#0000ff"]</[/COLOR][COLOR="#2b91af"]xsl:text[/COLOR][COLOR="#0000ff"]>[/COLOR]
       [COLOR="#0000ff"]</[/COLOR][COLOR="#a31515"]root[/COLOR][COLOR="#0000ff"]>[/COLOR]
   [COLOR="#0000ff"]</[/COLOR][COLOR="#2b91af"]xsl:template[/COLOR][COLOR="#0000ff"]>[/COLOR]
 
 
]]>
</root>
А вот как это выглядит после обработки BB-кодов
Цитата:
<xsl:templatematch="/">
<root>
<xsl:textdisable-output-escaping="yes">
&lt;![CDATA[
</xsl:text>

<xsl:apply-templatesselect="//office:body"/>

<xsl:textdisable-output-escaping="yes">
]]&gt;
</xsl:text>
</root>
</xsl:template>
Конечно, съедены отступы и пробелы между именами элементов и атрибутов, но в самом коде они есть. И главное вовсе не это, а то, что уже на данном этапе мы получили возможность автоматически окрашивать код в соответствии с тем, как он окрашен в документе, а в данном случае и в Visual Studio. Что касается проблемы с пробелами, то ее можно решить, заменив в выходном потоке пробелы символами с кодом 8194. Фильтр, в котором это сделано находится во вложении ColorizeTextooFilter_SpaceProblemCorrected.zip. А вот результат
Цитата:
   <xsl:templatematch="/">
         <root>
             <xsl:textdisable-output-escaping="yes">
  &lt;![CDATA[
  </xsl:text>
  
             <xsl:apply-templatesselect="//office:body"/>          
  
             <xsl:textdisable-output-escaping="yes">
  ]]&gt;
  </xsl:text>
         </root>
     </xsl:template>
Думаю, что тот, кто видел код XSLT в Visual Studio сможет по достоинству оценить результат. Хотя я не уверен, что такой код годится для копипасты, все-таки пробелы не настоящие.

>>
Вложения
Тип файла: zip ColorizeTextOOFilter.zip (1.4 Кб, 149 просмотров)
Тип файла: zip ColorizeTextooFilter_SpaceProblemCorrected.zip (1.5 Кб, 159 просмотров)
Размещено в Без категории
Просмотров 602 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.