Вычисляем размер шрифта.
Тот факт, что я решил поговорить о размере шрифта отдельно вовсе не означает, что мне просто хочется подробно обсмаковать каждое свойство. На самом деле в основном нам придется свойства запрашивать тем способом, который я уже описал и для этого нам надо будет только найти имя атрибута, в котором содержится интересующее нас свойство и выяснить какие значения он должен иметь в том или ином случае.
С размерами тоже все довольно просто, но, поскольку полученные знания мы применяем для генерации разметки Cyberforum, то тут следует обратить внимание на то, что размер шрифта мы получаем в точках, да еще и в формате ##pt, а нам надо привести все это дело к единицам, которые в HTML используются в элементе FONT.
Как соотносится одно с другим - мне пришлось выяснять и вот что я выяснил. Нашел в сети вот такую таблицу
Таблица размеров шрифта. Правда там все представлено в пикселях, а не в точках. Но нашел информацию о том, как перевести одно в другое. Далее примерно округляя написал вот такую функцию для перевода единиц.
Код xml | Выделить |
<xsl:function name="my:calculate-font-syze">
<xsl:param name="font-size"/>
<xsl:variable name="font-size-num"
select="number(substring-before($font-size, 'pt'))"/>
<xsl:choose>
<xsl:when test="$font-size-num
< 11">
1
</xsl:when>
<xsl:when test="$font-size-num
>= 11 and $font-size-num <= 13 ">
</xsl:when>
<xsl:when test="$font-size-num
>= 14 and $font-size-num <= 15 ">
3
</xsl:when>
<xsl:when test="$font-size-num
>= 16 and $font-size-num <= 17 ">
4
</xsl:when>
<xsl:when test="$font-size-num
>= 18 and $font-size-num <= 23 ">
5
</xsl:when>
<xsl:when test="$font-size-num
>= 24 and $font-size-num <= 35 ">
6
</xsl:when>
<xsl:when test="$font-size-num
>= 36">
7
</xsl:when>
</xsl:choose>
</xsl:function>
Обертывание в теги можно сделать более универсальным.
В принципе процесс упаковки текста в теги достаточно прост, однако если для каждого тега писать отдельную функцию, то получится очень много узкоспециализированного кода. Поэтому сейчас мы просто напишем более универсальные функции, с помощью которых потом одним махом будем обрабатывать любой узел.
Сначала пишем функцию, которая заключает текст в теги одного типа.
Код xml | Выделить |
<xsl:function name="my:wrap-with-tag">
<xsl:param name="content"/>
<xsl:param name="tag"/>
<xsl:variable name="without-value"
select="if (contains($tag, '=')) then substring-before($tag, '=') else $tag"/>
<xsl:value-of select="
if ($tag != '')
then concat('[', $tag, ']', $content, '[/', $without-value, ']')
else $content"
/>
</xsl:function>
Далее нам понадобится функция, которая будет получать список тегов и оборачивать содержимое во все по очереди, последовательно вызывая только что показанную функцию. Помимо содержимого и списка тегов функция еще имеет параметр index, он нужен для последовательного обхода списка тегов при рекурсивном вызове. К сожалению в XSLT-функциях необязательные параметры не поддерживаются, поэтому при вызове функции "вручную" параметру index всегда надо передавать 1.
Код xml | Выделить |
<xsl:function name="my:wrap-with-tags">
<xsl:param name="content"/>
<xsl:param name="tags"/>
<xsl:param name="index"/>
<xsl:value-of select="
if ($index >= fn:count($tags))
then my:wrap-with-tag($content, $tags[$index])
else my:wrap-with-tags(my:wrap-with-tag($content, $tags[$index]), $tags, $index + 1)
" />
</xsl:function>
Код xml | Выделить |
<xsl:function name="my:calculate-styles">
<xsl:param name="node"/>
<xsl:variable name="I"
select="my:style-property-value($node, 'fo:font-style')"/>
<xsl:variable name="B"
select="my:style-property-value($node, 'fo:font-weight')"/>
<xsl:variable name="U"
select="my:style-property-value($node, 'style:text-underline-style')"/>
<xsl:variable name="S"
select="my:style-property-value($node, 'style:text-line-through-style')"/>
<xsl:variable name="SIZE"
select="my:style-property-value($node, 'fo:font-size')"/>
<xsl:variable name="COLOR"
select="my:style-property-value($node, 'fo:color')"/>
<xsl:variable name="content">
<xsl:value-of select="$node"/>
</xsl:variable>
<xsl:variable name="calculated-size"
select="my:calculate-font-syze($SIZE)"/>
<xsl:value-of select="my:wrap-with-tags($node,
(
(if ($I = 'italic') then 'I' else ''),
(if ($B = 'bold') then 'B' else ''),
(if ($U = 'solid') then 'U' else ''),
(if ($S = 'solid') then 'S' else ''),
(if ($calculated-size != '') then concat('SIZE=', $calculated-size) else ''),
(if ($COLOR != '') then concat('COLOR=', $COLOR) else '')), 1)" />
</xsl:function>
Код xml | Выделить |
<xsl:template match="text()">
<xsl:value-of select="my:calculate-styles(.)"
disable-output-escaping="yes"/>
</xsl:template>
Код xml | Выделить |
<?xml version="1.0"
encoding="UTF-8"?>
<root>
<![CDATA[
[COLOR=#2e74b5][SIZE=4]Заголовок 1[/SIZE][/COLOR]
  Обычный текст
  [COLOR=#2e74b5]Заголовок 2[/COLOR]
  [COLOR=#1f4d78]Заголовок 3[/COLOR]
  [COLOR=#2e74b5][I]Заголовок
4[/I][/COLOR]
  
  [COLOR=#2e74b5]Заголовок
5[/COLOR]
  [COLOR=#1f4d78]Заголовок
6[/COLOR]
  [COLOR=#1f4d78][I]Заголовок
7[/I][/COLOR]
  [SIZE=6]Название[/SIZE]
  [COLOR=#5a5a5a]Подзаголовок[/COLOR]
  [COLOR=#5b9bd5][I]Сильное
выделение[/I][/COLOR]
  [B]Строгий[/B]
  [COLOR=#404040][B][I]Цитата
2[/I][/B][/COLOR]
  [COLOR=#5a5a5a]Слабая
ссылка[/COLOR]
  [COLOR=#5b9bd5][B]Сильная
ссылка[/B][/COLOR]
  
  [B][I]Название книги[/I][/B]
  [B][I]Абзац списка.[/I][/B]
  [B]Жирный[/B]
  [I]Курисив[/I]
  [U]Подчеркнутый[/U]
  [S]Перечекнутый[/S]
  ХНижний индекс
  ХВерхний идекс
  [SIZE=7]Крупный шрифт 72[/SIZE]
  [SIZE=1]Мелкий шрифт 8[/SIZE]
  Левое выравнивание
  Выравнивание по центру
  Правое выравнивание
  Первый пункт маркированного списка
  Второй пункт маркированного списка
  
  Первый пункт                                                                                                           нумерованного списка
  Пункт 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][U]Ссылка на гуголь[/U][/COLOR]
  
  /*Далее картинка*/
  
  Закладка
  Текст с отступом 2 см
  Ссылка на сноску1[SIZE=1]Сноска на странице[/SIZE]
  .
  
  
]]>
</root>
Обычный текст
Заголовок 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Сноска на странице
.
Что ж, текст все больше похож на оригинальный документ, а значит - мы на верном пути.
Отступы
С отступами не все так просто. Отступы задаются в стиле абзаца атрибутом fo:margin-left. Значением будет дробное число и единица измерения. В качестве единицы измерения в нашем документе используются сантиметры, на них мы и будем ориентироваться. Для элемента с отступом в полтора сантиметра атрибут будет иметь значение 1.5cm. Проблема здесь в том, что ширина отступа может быть указана достаточно точно, в документе я видел отступы с точностью до третьего десятичного знака, а у нас в арсенале только тег indent, либо несколько вложенных тегов indent. Стало быть задача будет в том, чтобы округлить, выполнить преобразование типов данных и "наклепать" приблизительно нужное количество отступов. Кроме того, поскольку отступы будут вычисляться для элементов text:p и text:h, следует помнить о том, что функция поиска значения свойства стиля рассчитана на то, что ей первоначально передавался текстовый узел и она начинала поиск не с самого узла, а с контейнера этого узла. Таким образом, для поиска значения свойств элементов, мы могли бы переделать функцию, но будет проще найти первый дочерний узел абзаца и передавать функции именно его. Переделанный шаблон будет выглядеть так.
Код xml | Выделить |
<xsl:template match="text:h|text:p">
<xsl:variable name="app-t">
<xsl:apply-templates/>
</xsl:variable>
<xsl:variable name="indent"
select="substring-before(my:style-property-value(./*[1], 'fo:margin-left'), 'cm')"/>
<xsl:choose>
<xsl:when test="$indent
= '' or starts-with($indent, '0')">
<xsl:value-of select="$app-t"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="indent-width"
select="fn:ceiling(number($indent)) cast as xsd:integer"/>
<xsl:variable name="indent-count"
select="$indent-width"
as="xsd:integer"/>
<xsl:value-of select="my:wrap-with-tags($app-t,
for $i in (1 to $indent-count) return 'indent' , 1)"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>
</xsl:text>
</xsl:template>
Ссылки
Об обычных ссылках писать особенно нечего, код предельно ясен: элемент text:a, адрес указан в атрибуте xlink:href. То есть вставка простого шаблона обрабатывает ссылки
Код xml | Выделить |
<xsl:template match="text:a">
<xsl:variable name="app-t">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="concat('[URL="',
@xlink:href, '"]', $app-t, '[/URL]')"/>
</xsl:template>
Во-первых, "местные" ссылки - в документе оформляются так же как и внешние, а нам надо для внешних создавать тег URL, а для "местных" ALINK. Кроме того, ссылки на элементы текущей страницы имеют адреса, начинающиеся с диеза #. Учитывая эти обстоятельства перепишем шаблон следующим образом.
Код xml | Выделить |
<xsl:template match="text:a">
<xsl:variable name="app-t">
<xsl:apply-templates />
</xsl:variable>
<xsl:choose>
<xsl:when test="starts-with(@xlink:href,
'#')">
<xsl:value-of select="concat('[ALINK="',
substring-after(@xlink:href, '#'), '"]', $app-t, '[/ALINK]')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('[URL="',
@xlink:href, '"]', $app-t, '[/URL]')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Комментариев нет :
Отправить комментарий