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>
Другие вопросы по тегам