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

 </xsclass="underline" template>

 <xsclass="underline" template match="@*|node()">

  <xsclass="underline" copy>

   <xsclass="underline" apply-templates select="@*|node()"/>

  </xsclass="underline" copy>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Если текущая планета расположена после Меркурия, я могу вставить сообщение в ее элемент <DISTANCE>. Результат следующий:

<?xml version="1.0" encoding-"utf-8"?>

<?xml-stylesheet type="text/xml" href="planets.xsl"?>

<PLANETS>

 <PLANET>

  <NAME>Mercury</NAME>

  <MASS UNITS="(Earth = 1)">.0553</MASS>

  <DAY UNITS="days">58.65</DAY>

  <RADIUS UNITS="miles">1516</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.983</DENSITY>

  <DISTANCE UNITS="million miles">43.4</DISTANCE> <!--В перигелии-->

 </PLANET>

 <PLANET>

  <NAME>Venus</NAME>

  <MASS UNITS="(Earth = 1)">.815</MASS>

  <DAY UNITS="days">116.75</DAY>

  <RADIUS UNITS="miles">3716</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.943</DENSITY>

  <DISTANCE>This planet is farther from the Sun than Mercury.</DISTANCE> <!--В перигелии-->

 </PLANET>

 <PLANET>

  <NAME>Earth</NAME>

  <MASS UNITS="(Earth = 1)">1</MASS>

  <DAY UNITS="days">1</DAY>

  <RADIUS UNITS="miles">2107</RADIUS>

  <DENSITY UNITS="(Earth = 1)">1</DENSITY>

  <DISTANCE>This planet is farther from the Sun than Mercury.</DISTANCE> <!--В перигелии-->

 </PLANET>

</PLANETS>

Применение оси preceding-sibling

Ось preceding-sibling содержит всех предшествующих братьев контекстного узла. Заметьте, что если контекстным узлом является узел атрибута или узел пространства имен, ось preceding-sibling будет пуста.

Что, если, например, вам нужно создать шаблон, который будет выбирать только элементы <DISTANCE> в элементе <PLANET> Меркурия? Для этого можно проверить, существуют ли братья, предшествующие элементу <DISTANCE>, которые являются элементами <NAME> со строковым значением «Mercury». Если применить ось preceding-sibling (листинг 7.14), поиск будет ограничен текущим элементом <PLANET>, что означает, что Меркурий не будет выбран, если вы только не находитесь в нужном элементе <PLANET>.

Листинг 7.14. Применение оси preceding-sibling

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.0"

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

 <xsclass="underline" output method="xml"/>

 <xsclass="underline" template match="DISTANCE[preceding-sibling::*='Mercury']">

  <DISTANCE>This is the planet Mercury, closest to the Sun.</DISTANCE>

 </xsclass="underline" template>

 <xsclass="underline" template match="@*|node()">

  <xsclass="underline" copy>

   <xsclass="underline" apply-templates select="@*|node()"/>

  </xsclass="underline" copy>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

А вот результат:

<?xml version="1.0" encoding="utf-8"?>

<?xml-stylesheet type="text/xml" href="planets.xsl"?>

<PLANETS>

 <PLANET>

  <NAME>Mercury</NAME>

  <MASS UNITS="(Earth = 1)">.0553</MASS>

  <DAY UNITS="days">58.65</DAY>

  <RADIUS UNITS="miles">1516</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.983</DENSITY>

  <DISTANCE>This is the planet Mercury, closest to the Sun.</DISTANCE> <!--В перигелии-->

 </PLANET>

 <PLANET>

  <NAME>Venus</NAME>

  <MASS UNITS="(Earth = 1)">.815</MASS>

  <DAY UNITS="days">116.75</DAY>

  <RADIUS UNITS="miles">3716</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.943</DENSITY>

  <DISTANCE UNITS="million miles">66.8</DISTANCE><!--B перигелии-->

 </PLANET>

 <PLANET>

  <NAME>Earth</NAME>

  <MASS UNITS="(Earth = 1)">1</MASS>

  <DAY UNITS="days">1</DAY>

  <RADIUS UNITS="miles">2107</RADIUS>

  <DENSITY UNITS="(Earth = 1)">1</DENSITY>

  <DISTANCE UNITS="million miles">128.4</DISTANCE><!--B перигелии-->

 </PLANET>

</PLANETS>

Применение оси self

Ось self содержит только контекстный узел. В соответствии с одним из сокращений XPath, как мы увидим дальше, вместо «self::node()» можно использовать «.».

Эту ось полезно иметь в виду, поскольку, как вы помните из главы 4, если не задать ось, осью по умолчанию будет child::, а в некоторых случаях вам может понадобиться обратиться к действующему узлу. Например, [self::PLANET] примет значение истины только если контекстным узлом будет элемент <PLANET>.

В следующем примере я объединяю шаблоны для элементов <NAME> и <MASS> в один шаблон. Поскольку у этих элементов разный формат, я должен обращаться с ними по-разному внутри одного и того же шаблона (что можно сделать проверкой значений оси self::NAME, которая возвращает непустой набор узлов, если контекстным, узлом является элемент <NAME>, и self::MASS, возвращающей непустой набор узлов, если контекстным узлом является элемент <MASS>):

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

 <TR>

  <TD><xsclass="underline" apply-templates select="NAME"/></TD>

  <TD><xsclass="underline" apply-templates select="MASS"/></TD>

  <TD><xsclass="underline" apply-templates select="RADIUS"/></TD>

  <TD><xsclass="underline" apply-templates select="DAY"/></TD>

 </TR>

</xsclass="underline" template>

<xsclass="underline" template match="NAME | MASS">

 <xsclass="underline" if test="self::NAME">

  <xsclass="underline" value-of select="."/>

 </xsclass="underline" if>

 <xsclass="underline" if test="self::MASS">

  <xsclass="underline" value-of select="."/>

  <xsclass="underline" text> </xsclass="underline" text>

  <xsclass="underline" value-of select="@UNITS"/>