Стивен Холзнер - XSLT
<?xml version="1.0"?>
<?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>
.
.
.
Это можно сделать при помощи элемента <xsl:value-of>.
Доступ к значениям узлов
Элемент <xsl:value-of> записывает в результирующий документ строковое значение выражения; в частности, с его помощью можно возвратить значение узла, которым для элемента будет заключенный в элемент текст. Атрибуту выбора элемента <xsl:value-of> можно присвоить выражение XPath, задающее узел или набор узлов. В шаблоне, задающем элементы <PLANET>, обратиться к дочернему элементу <MASS> можно при помощи выражения XPath "child::MASS". Как мы увидим в главе 4, выражения XPath можно писать разными способами: например, вместо "child::MASS" можно просто написать "MASS". Таким образом, получить данные дочерних элементов, таких как <MASS>, <DAY> и т.д., можно следующим способом (листинг 3.1).
Листинг 3.1. Полная версия planets.xsl<?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>
<Н1>
The Planets Table
</Н1>
<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">
<TR>
<TD><xsl:value-of select="NAME"/></TD>
<TD><xsl:value-of select="MASS"/></TD>
<TD><xsl:value-of select="RADIUS"/></TD>
<TD><xsl:value-of select="DAY"/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
Создание образцов выбора
Как вы могли ожидать, исходя из того, что "child::MASS" можно представить в виде "MASS" и применения шаблонов, таких как "/", "/PLANETS" и т.д., вплотную познакомиться с созданием образцов выбора не так-то просто — этому посвящена вся глава 4.
Образцы выбора (match pattern) являются подмножеством полного языка XPath, их можно использовать в элементах <xsl:template>, <xsl:key> и <xsl:number>. В частности, в образец можно установить атрибут match у <xsl:template> и <xsl:key>, и атрибуты count и from элемента <xsl:number>. В следующем списке приведен ряд примеров образцов выбора, много других примеров будет показано в главе 4 при подробном обсуждении использования XPath для выбора узлов и атрибутов:
• "/" выбирает корневой узел;
• "*" выбирает элементы узлов (но не всех узлов, как зачастую ошибочно полагают);
• "PLANET" выбирает элементы <PLANET>;
• "PLANET/MASS" выбирает все элементы <MASS>, дочерние для элемента <PLANET>;
• "//PLANET" выбирает все элементы <PLANET>, производные от корневого узла;
• "." выбирает текущий узел (технически это не образец выбора, а выражение XPath, как мы увидим в главе 7).
Образцы можно также использовать в атрибуте select элементов <xsl:apply-templates>, <xsl:value-of>, <xsl:for-each>, <xsl:copy-of> и <xsl:sort>; фактически атрибут select этих элементов может содержать полные выражения XPath, а не только образцы выбора. Атрибут select элемента <xsl:value-of> определяет дочерний узел, значение которого нужно получить:
<xsl:template match="PLANET">
<TR>
<TD><xsl:value-of select="NAME"/></TD>
<TD><xsl:value-of select="MASS"/></TD>
<TD><xsl:value-of select="RADIUS"/></TD>
<TD><xsl:value-of select="DAY"/></TD>
</TR>
</xsl:template>
Теперь пора воспользоваться атрибутом select элемента <xsl:apply-templates>, поскольку это даст нам возможность указать, какой шаблон использовать и когда.
Выбор применяемого шаблона
Вплоть до нынешнего момента я использовал только версию элемента <xsl:apply-templates> по умолчанию, как, например:
<TABLE BORDER="2">
<TR>
<TD>Name</TD>
<TD>Mass</TD>
<TD>Radius</TD>
<TD>Day</TD>
</TR>
<xsl:apply-templates/>
</TABLE>
Простое использование только <xsl:apply-templates/> указывает процессору XSLT осуществлять поиск всех шаблонов, выбирающих дочерние узлы контекстного узла, — это использование по умолчанию. Однако иногда это не лучший вариант, поскольку может потребоваться применять шаблоны в определенном порядке или иным образом выбрать применяемые шаблоны (последнее можно сделать при помощи атрибута select элемента <xsl:apply-templates/>).
Например, до сих пор мы только получали значение каждого элемента <MASS>, <DAY> и <RADIUS> при помощи <xsl:value-of>:
<?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
</Н1>
<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">
<TR>
<TD><xsl:value-of select="NAME"/></TD>
<TD><xsl:value-of select="MASS"/></TD>
<TD><xsl:value-of select="RADIUS"/></TD>
<TD><xsl:value-of select="DAY"/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
Здесь только извлекается «сырое» строковое значение каждого узла, которое помещается в HTML-таблицу. Однако может потребоваться дополнительная обработка каждого элемента — например, получить также значения атрибутов UNITS каждого элемента и отобразить их:
<?xml version="1.0"?>
<?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>
.
.
.
Для этого нельзя просто применить элемент <xsl:value-of>, поскольку он вернет значение узла только как текст, а не как значения атрибута. Вместо этого нужно создать новый набор шаблонов, по одному для каждого интересующего нас элемента: <MASS>, <RADIUS> и <DAY>. У элемента <NAME> нет никаких атрибутов, поэтому для него не нужны шаблоны — нужно только значение узла. Каждому из этих новых шаблонов требуется получить значение элемента, а также значение атрибута UNITS.
Чтобы быть уверенным в том, что эти новые шаблоны применяются в правильном порядке, соответствующем заголовкам HTML-таблицы, я явно перечислю все новые шаблоны, выбирая их один за другим при помощи атрибута select:
<?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