- Решение проблемы разделения на строки.
- Демонстрация работы подсветки синтаксиса кода
Решение проблемы разделения на строки.
Коль скоро мы начали с определения цвета, возьмемся за раскрашивание текста. То есть целью будет получение текста документа, раскрашенного с помощью 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="', $color, '"]', $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">
<![CDATA[
</xsl:text>
<xsl:apply-templates select="//office:body"/>
<xsl:text disable-output-escaping="yes">
]]>
</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&Второй пункт нумерованного списка[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&Второй пункт нумерованного спискаТекст красного цветаТекст синего цветаВыделение желтым/*Далее таблица*/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&
Второй пункт нумерованного списка
Текст красного цвета
Текст синего цвета
Выделение желтым
/*Далее таблица*/
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&
Второй пункт нумерованного списка
Текст до десяти пробелов Текст после десяти пробелов
[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"]<[/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"]>[/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">
<![CDATA[
</xsl:text>
<xsl:apply-templatesselect="//office:body"/>
<xsl:textdisable-output-escaping="yes">
]]>
</xsl:text>
</root>
</xsl:template>
| Конечно, съедены отступы и пробелы между именами элементов и атрибутов, но в самом коде они есть. И главное вовсе не это, а то, что уже на данном этапе мы получили возможность автоматически окрашивать код в соответствии с тем, как он окрашен в документе, а в данном случае и в Visual Studio. Что касается проблемы с пробелами, то ее можно решить, заменив в выходном потоке пробелы символами с кодом 8194. Фильтр, в котором это сделано находится во вложении ColorizeTextooFilter_SpaceProblemCorrect ed.zip. А вот результат
<xsl:template match="/">
<root>
<xsl:text disable-output-escaping="yes">
<![CDATA[
</xsl:text>
<xsl:apply-templates select="//office:body"/>
<xsl:text disable-output-escaping="yes">
]]>
</xsl:text>
</root>
</xsl:template>
| Думаю, что тот, кто видел код XSLT в Visual Studio сможет по достоинству оценить результат. Хотя я не уверен, что такой код годится для копипасты, все-таки пробелы не настоящие.
>>
|