<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-документ.
<!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.
<?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>
Результатом этого преобразования будет следующий документ.