Выбрать главу

 <xsclass="underline" template match="/">

  <svg width="200" height="200">

   <desc>Simple line-based figure</desc>

   <xsclass="underline" apply-templates select="точки"/>

  </svg>

 </xsclass="underline" template>

 <xsclass="underline" template match="точки">

  <g style="stroke:black; stroke-width:2">

   <xsclass="underline" apply-templates select="точка"/>

  </g>

 </xsclass="underline" template>

 <xsclass="underline" template match="точка">

  <line

   x1="{@x + 100}"

   y1="{@y + 100}"

   x2="{following-sibling::точка[1]/@x + 100}"

   y2="{following-sibling::точка[1]/@y + 100}">

   <xsclass="underline" if test="position() = last()">

    <xsclass="underline" attribute name="x2">

     <xsclass="underline" value-of

      select="preceding-sibling::точка[last()]/@x + 100"/>

    </xsclass="underline" attribute>

    <xsclass="underline" attribute name="y2">

     <xsclass="underline" value-of

      select="preceding-sibling::точка[last()]/@y + 100"/>

    </xsclass="underline" attribute>

   </xsclass="underline" if>

  </line>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Результатом этого преобразования является следующий SVG-документ.

Листинг 10.5. Выходящий SVG-документ

<!DOCTYPE svg

 PUBLIC "-//W3C//DTD SVG 1.0//EN"

 "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">

 <desc>Simple line-based figure</desc>

 <g style="stroke:black; stroke-width:2">

  <line x1="50" y1="50" x2="150" y2="50"/>

  <line x1="150" y1="50" x2="150" y2="150"/>

  <line x1="150" y1="150" x2="50" y2="150"/>

  <line x1="50" y1="150" x2="50" y2="50"/>

 </g>

</svg>

На рис. 10.1 приведен пример визуального представления этого документа.

Рис. 10.1. Визуальное представление полученного SVG-документа

Предположим теперь, что нам нужно не просто создать по данному множеству точек набор соединяющих их линий, но еще и произвести некоторые геометрические преобразования, например поворот на заданный в градусах угол α.

Формулы преобразования координат при повороте чрезвычайно просты:

x = x'∙cos(α) − y∙sin(α),

у = x'∙sin(α) + x'∙cos(α),

где x' и y' — старые координаты точки, x и y — новые координаты точки, а α — угол поворота. Единственная загвоздка состоит в том, что функций sin и cos в базовой библиотеке XPath нет.

Самым простым выходом в такой ситуации является использование расширений. Например, в случае XSLT-процессора, который может использовать Java-расширения (Saxon, Xalan, Oracle XSLT Processor и так далее) надо будет лишь только объявить пространство имен вида:

xmlns:math="java:java.lang.Math"

и использовать функции math:sin и math:cos.

Листинг 10.6. Преобразование, осуществляющее поворот

<?xml version="1.0" encoding="windows-1251"?>

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

 xmlns="http://www.w3.org/2000/svg"

 xmlns:math="java:java.lang.Math">

 <xsclass="underline" output

  indent="yes"

  doctype-public="-//W3C//DTD SVG 1.0//EN"

  doctype-system="http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"/>

 <xsclass="underline" param name="alpha" select="30"/>

 <xsclass="underline" variable name="alpha-radian" select="3.14 * ($alpha div 180)"/>

 <xsclass="underline" template match="/">

  <svg width="200" height="200">

   <desc>Simple line-based figure</desc>

   <xsclass="underline" apply-templates select="точки"/>

  </svg>

 </xsclass="underline" template>

 <xsclass="underline" template match="точки">

  <g style="stroke:black; stroke-width:2">

   <xsclass="underline" apply-templates select="точка"/>

  </g>

 </xsclass="underline" template>

 <xsclass="underline" template match="точка">

  <xsclass="underline" variable name="x1" select="@x"/>

  <xsclass="underline" variable name="y1" select="@y"/>

  <xsclass="underline" variable name="x2r">

   <xsclass="underline" choose>

    <xsclass="underline" when test="position() = last()">

     <xsclass="underline" value-of select="preceding-sibling::точка[last()]/@x"/>

    </xsclass="underline" when>

    <xsclass="underline" otherwise>

     <xsclass="underline" value-of select="following-sibling::точка[1]/@x"/>

    </xsclass="underline" otherwise>

   </xsclass="underline" choose>

  </xsclass="underline" variable>

  <xsclass="underline" variable name="y2r">

   <xsclass="underline" choose>

    <xsclass="underline" when test="position() = last()">

     <xsclass="underline" value-of select="preceding-sibling::точка[last()]/@y"/>

    </xsclass="underline" when>

    <xsclass="underline" otherwise>

     <xsclass="underline" value-of select="following-sibling::точка[1]/@y"/>

    </xsclass="underline" otherwise>

   </xsclass="underline" choose>

  </xsclass="underline" variable>

  <xsclass="underline" variable name="x2" select="number($x2r)"/>

  <xsclass="underline" variable name="y2" select="number($y2r)"/>

  <line

   x1="{$x1 * math:cos($alpha-radian) -

        $y1 * math:sin($alpha-radian) + 100}"

   y1="{$x1 * math:sin($alpha-radian) +

        $y1 * math:cos($alpha-radian) + 100}"

   x2="{$x2 * math:cos($alpha-radian) -

        $y2 * math:sin($alpha-radian) + 100}"

   y2="{$x2 * math:sin($alpha-radian) +

        $y2 * math:cos($alpha-radian) + 100}"/>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Результатом этого преобразования будет следующий документ.