=> Главная База Знаний Xslt Примеры образцов


Примеры образцов

Примеры образцов

Изучать образцы лучше всего на примерах. Предположим, что нам требуется преобразовать

planets.xml
в
planets.html
, но сохранить только первую планету, Меркурий. Это можно сделать при помощи предиката
[position()<2]
, так как позиция первой планеты равна 1, следующей — 2, и т.д. Заметьте, однако, что <; является управляющим символом для процессоров XSLT, начинающим разметку, поэтому вместо < необходимо использовать
<
. И отметьте, что для того чтобы убрать из
planets.xml
другие элементы, для них нужно предоставить пустой шаблон, что можно сделать при помощи предиката
[position()>=2]
(листинг 4.10).

Листинг 4.10. Выбор только Меркурия

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:template match="/PLANETS">

  <HTML>

   <HEAD>

    <TITLE>

     The Planets Table

    </TITLE>

   </HEAD>

   <BODY>

    <H1>

     The Planets Table

    </H1>

    <TABLE BORDER="2">

     <TR>

      <TD>Name</TD>

      <TD>Mass</TD>

      <TD>Radius</TD>

      <TD>Day</TD>

     </TR>

     <xsl:apply-templates/>

    </TABLE>

   </BODY>

  </HTML>

 </xsl:template>


 <xsl:template match="PLANET[position() < 2]">

  <TR>

   <TD><xsl:value-of select="NAME"/></TD>

   <TD><xsl:apply-templates select="MASS"/></TD>

   <TD><xsl:apply-templates select="RADIUS"/></TD>

   <TD><xsl:apply-templates select="DAY"/></TD>

  </TR>

 </xsl:template>


 <xsl:template match="PLANET[position() >= 2]">

 </xsl:template>


 <xsl:template match="MASS">

  <xsl:value-of select="."/>

  <xsl:text> </xsl:text>

  <xsl:value-of select="@UNITS"/>

 </xsl:template>


 <xsl:template match="RADIUS">

  <xsl:value-of select="."/>

  <xsl:text> </xsl:text>

  <xsl:value-of select="@UNITS"/>

 </xsl:template>


 <xsl:template match="DAY">

  <xsl:value-of select="."/>

  <xsl:text> </xsl:text>

  <xsl:value-of select="@UNITS"/>

 </xsl:template>

</xsl:stylesheet>

Вот результирующий документ — отметьте, что сохранилась только первая планета, Меркурий:

<HTML>

 <HEAD>

  <TITLE>

   The Planets Table

  </TITLE>

 </HEAD>

 <BODY>

  <H1>

   The Planets Table

  </H1>

  <TABLE BORDER="2">

   <TR>

    <TD>Name</TD>

    <TD>Mass</TD>

    <TD>Radius</TD>

    <TD>Day</TD>

   </TR>

   <TR>

    <TD>Mercury</TD>

    <TD>.0553 (Earth = 1)</TD>

    <TD>1516 miles</TD>

    <TD>58.65 days</TD>

   </TR>

  </TABLE>

 </BODY>

</HTML>

В следующем примере в элемент

<PLANET>
Земли были добавлены атрибуты
COLOR
(цвет) и
POPULATED
(населена):

<PLANET COLOR="blue" POPULATED="yes">

 <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">1284</DISTANCE><!--B перигелии-->

</PLANET>

Как выбрать только элементы, имеющие оба атрибута,

COLOR
и
POPULATED
? Можно применить предикат "
[@COLOR and @POPULATED]
". Чтобы убрать другие элементы — так, чтобы правило по умолчанию не поместило их текст в результирующий документ, — можно применить предикат "
[not(@COLOR) or not(@POPULATED)]
", как показано в листинге 4.11.

Листинг 4.11. Выбор только элементов с двумя атрибутами COLOR и POPULATED

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:template match="/PLANETS">

  <HTML>

   <HEAD>

    <TITLE>

     Colorful, Populated Planets

    </TITLE>

   </HEAD>

   <BODY>

    <H1>

     Colorful, Populated Planets

    </H1>

    <TABLE BORDER="2">

     <TR>

      <TD>Name</TD>

      <TD>Mass</TD>

      <TD>Radius</TD>

      <TD>Day</TD>

     </TR>

     <xsl:apply-templates/>

    </TABLE>

   </BODY>

  </HTML>

 </xsl:template>


 <xsl:template match="PLANET[@COLOR and @POPULATED]">

  <TR>

   <TD><xsl:value-of select="NAME"/></TD>

   <TD><xsl:apply-templates select="MASS"/></TD>

   <TD><xsl:apply-templates select="RADIUS"/></TD>

   <TD><xsl:apply-templates select="DAY"/></TD>

  </TR>

 </xsl:template>


 <xsl:template match="PLANET[not(@COLOR) or not(@POPULATED)]">

 </xsl:template>


 <xsl:template match="MASS">

  <xsl:value-of select="."/>

  <xsl:text> </xsl:text>

  <xsl:value-of select="@UNITS"/>

 </xsl:template>


 <xsl:template match="RADIUS">

  <xsl:value-of select="."/>

  <xsl:text> </xsl:text>

  <xsl:value-of select="@UNITS"/>

 </xsl:template>


 <xsl:template match="DAY">

  <xsl:value-of select="."/>

  <xsl:text> </xsl:text>

  <xsl:value-of select="@UNITS"/>

 </xsl:template>

</xsl:stylesheet>

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

<HTML>

 <HEAD>

  <TITLE>

   Colorful, Populated Planets

  </TITLE>

 </HEAD>

 <BODY>

  <H1>

   Colorful, Populated Planets

  </H1>

  <TABLE BORDER="2">

   <TR>

    <TD>Name</TD>

    <TD>Mass</TD>

    <TD>Radius</TD>

    <TD>Day</TD>

   </TR>

   <TR>

    <TD>Earth</TD>

    <TD>1 (Earth = 1)</TD>

    <TD>2107 miles</TD>

    <TD>1 days</TD>

   </TR>

  </TABLE>

 </BODY>

</HTML>

Этот документ показан на 3.

Примеры образцов

3. Применение предикатов XPath для проверки атрибутов


В следующем примере я копирую

planets.xml
в новый XML-документ и изменяю текст в элементе
<NAME>
Венеры на "
The Planet of Love
" (планета любви). Для этого я сначала копирую в результирующий документ все узлы и атрибуты:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="@*|node()">

  <xsl:copy>

   <xsl:apply-templates select="@*|node()"/>

  </xsl:copy>

 </xsl:template>

 .

 .

 .

Теперь я добавлю новое правило, выбирающее элементы

<NAME>
с текстом "
Venus
" (Венера) по образцу "
NAME[text()='Venus']
". Хотя элементы
<NAME>
удовлетворяют обоим правилам этой таблицы стилей, правило с образцом "
NAME[text()='Venus']
" осуществляет более узкий выбор, поэтому для элемента
<NAME>
Венеры процессор XSLT применит его:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="@*|node()">

  <xsl:copy>

   <xsl:apply-templates select="@*|node()"/>

  </xsl:copy>

 </xsl:template>


 <xsl:template match="NAME[text() = 'Venus']">

  <NAME>

   The Planet of Love

  </NAME>

 </xsl:template>

</xsl: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 UNITS="million miles">43.4</DISTANCE><!--B перигелии-->

 </PLANET>

 <PLANET>

  <NAME>

   The Planet of Love

  </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>

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

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="@*|node()">

  <xsl:copy>

   <xsl:apply-templates select="@*|node()"/>

  </xsl:copy>

 </xsl:template>

 <xsl:template match="NAME[. = 'Venus']">

  <NAME>

   The Planet of Love

  </NAME>

 </xsl:template>

</xsl:stylesheet>

Имеет смысл привести как можно больше примеров — примеров XPath или образцов выбора никогда не бывает слишком много. Ниже приведен содержательный ряд примеров образцов выбора:

• 

PLANET
выбирает дочерние элементы
<PLANET>
контекстного узла;

• 

/PLANETS
выбирает корневой элемент
<PLANETS>
документа;

• 

*
выбирает все дочерние элементы контекстного узла;

• 

PLANET[3]
выбирает третьего ребенка
<PLANET>
контекстного узла;

• 

PLANET[last()]
выбирает последнего ребенка
<PLANET>
контекстного узла;

• 

PLANET[NAME]
выбирает детей
<PLANET>
контекстного узла, имеющих детей
<NAME>
;

• 

PLANET[DISTANCE]/NAME
выбирает все элементы
<NAME>
элементов
<PLANET>
, содержащих по крайней мере один элемент
<DISTANCE>
;

• 

PLANET[DISTANCE]/PLANET[DAY]
выбирает все элементы
<PLANET>
элементов
<PLANET>
, в которых элемент
<PLANET>
содержит по крайней мере один элемент
<DISTANCE>
, и элемент
<PLANET>
содержит по крайней мере один элемент
<DAY>
;

• 

РLANETS[РLАNET/DAY]
выбирает все элементы
<PLANETS>
, содержащие элементы
<PLANET>
как минимум с одним элементом
<DAY>
;

• 

PLANET[DISTANCE][NAME]
выбирает все элементы
<PLANET>
, имеющие элементы
<DISTANCE>
и
<NAME>
;

• 

PLANETS/PLANET[last()]
выбирает последний элемент
<PLANET>
в каждом элементе
<PLANETS>
;

• 

*/PLANET
выбирает всех внуков
<PLANET>
контекстного узла;

• 

/PLANETS/PLANET[3]/NAME[2]
выбирает второй элемент
<NAME>
третьего элемента
<PLANET>
элемента
<PLANETS>
;

• 

//PLANET
выбирает всех потомков
<PLANET>
корня документа;

• 

PLANETS//PLANЕТ
выбирает потомков элемента
<PLANET>
детей элемента
<PLANETS>
контекстного узла;

• 

//PLANET/NAME
выбирает все элементы
<NAME>
, дочерние по отношению к родителю
<PLANET>
;

• 

РLАNETS//PLАNET/DISTАNСЕ//РЕRIНЕLION
выбирает элементы
<PERIHELION>
везде внутри элемента
<DISTANCE>
элемента
<PLANET>
, везде внутри элемента
<PLANETS>
;

• 

@UNITS
выбирает атрибут
UNITS
контекстного узла;

• 

@*
выбирает все атрибуты контекстного узла;

• 

*[@UNITS]
выбирает все элементы с атрибутом
UNITS
;

• 

DENSITY/@UNITS
выбирает атрибут
UNITS
в элементах
<DENSITY>
;

• 

PLANET[not(@COLOR) or not(@SIZE)]
выбирает элементы
<PLANET>
, не имеющие обоих атрибутов
COLOR
и
SIZE
;

• 

PLANETS[@STAR="Sun"]//DENSITY
выбирает любой элемент
<DENSITY>
с элементом-предком
<PLANETS>
, имеющим атрибут
STAR
со значением "
Sun
";

• 

PLANET[NAME="Venus"]
выбирает детей
<PLANET>
контекстного узла, имеющих детей
<NAME>
с текстом "
Venus
";

• 

PLANET[NAME[1]="Venus"]
выбирает все элементы
<PLANET>
, у которых в первом элементе
<NAME>
содержится текст в "
Venus
";

• 

DAY[@UNITS!="million miles"]
выбирает все элементы
<PLANET>
, атрибут
UNITS
которых не равен "
million miles
";

• 

PLANET[@UNITS="days"]
выбирает всех детей
<PLANET>
контекстного узла, имеющих атрибут
UNITS
со значением "
days
";

• 

PLANET[6][@UNITS="days"]
выбирает шестого ребенка
<PLANET>
контекстного узла, только если у этого ребенка есть атрибут
UNITS
со значением "
days
", — что также можно записать как
PLANET[@UNITS="days"][6]
;

• 

PLANET[@COLOR and @UNITS]
выбирает всех детей
<PLANET>
контекстного узла, имеющих оба атрибута
COLOR
и
UNITS
;

• 

*[1][NAME]
выбирает любой элемент
<NAME>
, являющийся первым ребенком своего родителя;

• 

*[position() < 5]
выбирает первые пять детей контекстного узла;

• 

*[position() < 5][@UNIT]
выбирает первые пять детей контекстного узла с атрибутом
UNITS
;

• 

text()
выбирает все дочерние текстовые узлы контекстного узла;

• 

text()[starts-with(., "In the course of human events")]
выбирает все дочерние текстовые узлы контекстного узла, начинающиеся с "
In the course of human events
";

• 

/PLANETS[@UNITS="million miles"]
выбирает все элементы
PLANETS
, у которых значение атрибута
UNITS
равно "
million miles
";

• 

PLANET[/PLANETS/@UNITS=@REFERENCE]
выбирает все элементы
<PLANET>
, у которых значение атрибута
REFERENCE
такое же, как значение атрибута
UNITS
элемента
PLANETS
в корне документа;

• 

PLANET/*
выбирает все дочерние элементы элементов
PLANET
;

• PLANET/*/DAY выбирает все элементы DAY — правнуки элементов PLANET, являющиеся детьми контекстного узла;

• 

*/*
выбирает элементы-внуки текущего элемента;

• 

astrophysics:PLANET
выбирает элемент
PLANET
в пространстве имен «
astrophysics
»;

• 

astrophysics:*
выбирает любые элементы в пространстве имен «
astrophysics
»;

• 

PLANET[DAY and DENSITY]
выбирает все элементы
<PLANET>
, у которых есть по крайней мере один элемент
<DAY>
и один элемент
<DENSITY>
;

• 

PLANET[(DAY or DENSITY) and MASS]
выбирает все элементы
<PLANET>
, у которых есть по крайней мере один элемент
<DAY>
или один элемент
<DENSITY>
, а также по крайней мере один элемент
<MASS>
;

• 

PLANET[DAY and not(DISTANCE)]
выбирает все элементы
<PLANET>
, у которых есть по крайней мере один элемент
<DAY>
и нет элементов
<DISTANCE>
;

• 

PLANET[MASS=/STANDARD/REFERENCE/MASS]
выбирает все элементы
<PLANET>
, у которых значение элемента
<MASS>
равно значению элемента
/<STANDARD>/<REFERENCE>/<MASS>
.

На этом мы завершаем в данный момент рассмотрение образцов выбора; связанный материал приводится в главе 7 при рассмотрении выражений XPath. Глава 5 начинается с изучения способов работы с данными в XML-документах путем сортировки и принятия решения на основе значений данных.