xslt выберите родительский узел в зависимости от значения атрибута своего внукового узла
Я пытаюсь добавить различные теги к узлу в зависимости от значения атрибута его узла внука.
Пример ввода (таблица 1x3):
<table>
<row>
<cell row="1" column="1" >heading text one</cell>
</row>
<row>
<cell row="2" column="1" >body text one</cell>
</row>
<row>
<cell row="3" column="1" >body text two</cell>
</row>
</table>
Нужен вывод как это:
<TableElmt>
<HeadingElmt>
<RowElmt>
<CellElmt>heading text one</CellElmt>
</RowElmt>
</HeadingElmt>
<BodyElmt>
<RowElmt>
<CellElmt>body text one</CellElmt>
</RowElmt>
<RowElmt>
<CellElmt>body text two</CellElmt>
</RowElmt>
</BodyElmt>
</TableElmt>
По сути, я могу только решить, является ли строка строкой заголовка на основе элемента @row ячейки.
Вот что я попробовал:
<xsl:template name="matcheverything" match="table">
<xsl:apply-templates select="row" />
</xsl:template>
<xsl:template name="matchheadings" match="table[*/*/@row=1]">
<BodyElmt>
<xsl:apply-templates select="row" />
</BodyElmt>
</xsl:template>
<xsl:template match="row">
<xsl:choose>
<xsl:when test="*/@row=1">
<HeadingElmt><RowElmt>
<xsl:apply-templates select="cell"/>
</RowElmt></HeadingElmt>
</xsl:when>
<xsl:otherwise>
<RowElmt>
<xsl:apply-templates select="cell"/>
</RowElmt>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="cell">
<CellElmt><xsl:apply-templates select="*"/></CellElmt>
</xsl:template>
Я думал, что шаблон "matchheadings", имеющий более конкретное требование соответствия, должен распознавать строку заголовка, однако он фактически соответствует каждой строке в таблице.
Таким образом, мой фактический вывод из этой таблицы стилей - каждая строка рассматривается как строка заголовка - очень плохо:(
<TableElmt>
<HeadingElmt>
<RowElmt>
<CellElmt>heading text one</CellElmt>
</RowElmt>
<RowElmt>
<CellElmt>body text one</CellElmt>
</RowElmt>
<RowElmt>
<CellElmt>body text two</CellElmt>
</RowElmt>
</HeadingElmt>
</TableElmt>
2 ответа
Это преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="table">
<TableElmt>
<xsl:apply-templates/>
</TableElmt>
</xsl:template>
<xsl:template match="row[cell/@row='1']">
<HeadingElmt>
<xsl:apply-templates select="." mode="copy"/>
</HeadingElmt>
</xsl:template>
<xsl:template match="row[cell[not(@row='1')]][1]">
<BodyElmt>
<xsl:apply-templates select=".|following-sibling::row" mode="copy"/>
</BodyElmt>
</xsl:template>
<xsl:template match="row" mode="copy">
<RowElmt>
<xsl:apply-templates/>
</RowElmt>
</xsl:template>
<xsl:template match="cell">
<CellElmt>
<xsl:value-of select="."/>
</CellElmt>
</xsl:template>
<xsl:template match="row"/>
</xsl:stylesheet>
при применении к предоставленному документу XML:
<table>
<row>
<cell row="1" column="1" >heading text one</cell>
</row>
<row>
<cell row="2" column="1" >body text one</cell>
</row>
<row>
<cell row="3" column="1" >body text two</cell>
</row>
</table>
дает желаемый, правильный результат:
<TableElmt>
<HeadingElmt>
<RowElmt>
<CellElmt>heading text one</CellElmt>
</RowElmt>
</HeadingElmt>
<BodyElmt>
<RowElmt>
<CellElmt>body text one</CellElmt>
</RowElmt>
<RowElmt>
<CellElmt>body text two</CellElmt>
</RowElmt>
</BodyElmt>
</TableElmt>
Редактировать: Похоже, я пропустил это
По сути, я могу только решить, является ли строка строкой заголовка на основе элемента @row ячейки.
Эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="table">
<TableElmt>
<HeadingElmt>
<xsl:apply-templates select="row[cell/@row=1]"/>
</HeadingElmt>
<BodyElmt>
<xsl:apply-templates select="row[cell/@row!=1]"/>
</BodyElmt>
</TableElmt>
</xsl:template>
<xsl:template match="row">
<RowElmt>
<xsl:apply-templates/>
</RowElmt>
</xsl:template>
<xsl:template match="cell">
<CellElmt>
<xsl:apply-templates/>
</CellElmt>
</xsl:template>
</xsl:stylesheet>
Выход:
<TableElmt>
<HeadingElmt>
<RowElmt>
<CellElmt>heading text one</CellElmt>
</RowElmt>
</HeadingElmt>
<BodyElmt>
<RowElmt>
<CellElmt>body text one</CellElmt>
</RowElmt>
<RowElmt>
<CellElmt>body text two</CellElmt>
</RowElmt>
</BodyElmt>
</TableElmt>