#xml #xslt #richtext
#xml #xslt #richtext
Вопрос:
У меня есть XML со встроенным форматированием расширенного текста, который выглядит примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<richtext>
<pardef/>
<par><run>This is the </run><run>preamble.</run></par>
<pardef list='bullet'/>
<par><run>This is the </run><run>first bullet.</run></par>
<par><run>This is the second </run><run>bullet.</run></par>
</richtext>
</document>
Я пытаюсь сгенерировать следующий HTML:
<p>This is the preamble.</p>
<ul>
<li>This is the first bullet</li>
<li>This is the second bullet</li>
<ul>
Я попробовал следующий XSL, но он не работает. У меня такое чувство, что мне нужно использовать СЛЕДУЮЩИЙ-SIBLING, но я не уверен, как это сделать.
<xsl:choose>
<xsl:when test="document/richtext/pardef[@list] ='bullet'">
<ul>
<xsl:for-each select="document/richtext/par/run">
<li>
<xsl:for-each select="run">
<xsl:value-of select="."/>
</xsl:for-each>
</li>
</xsl:for-each>
</ul>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:for-each select="document/richtext/par">
<p>
<xsl:for-each select="run">
<xsl:value-of select="."/>
</xsl:for-each>
</p>
</xsl:for-each>
</p>
</xsl:otherwise>
</xsl:choose>
Ответ №1:
Один подход с XSLT 2.0 и вашим «дизайном»:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="key-for-par" match="document/richtext/par" use="generate-id(preceding-sibling::pardef[1])"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="document/richtext/pardef" />
</xsl:template>
<xsl:template match="pardef[@list = 'bullet']">
<ul>
<xsl:for-each select="key('key-for-par', generate-id(.))">
<li>
<xsl:value-of select="run" separator=""/>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="pardef[not(@list)]">
<p>
<xsl:for-each select="key('key-for-par', generate-id(.))">
<p>
<xsl:value-of select="run" separator=""/>
</p>
</xsl:for-each>
</p>
</xsl:template>
</xsl:stylesheet>
ПРАВКА 1: улучшенная версия.
Комментарии:
1. Это сработало! Хотя на самом деле я использую XSLT 2.0, о котором я должен был упомянуть ранее. Имеет ли это значение?
2. Да, это так. Посмотрите на редактирование 1 , есть еще больше способов решения.
3. Еще раз спасибо! Можете ли вы пояснить, почему группировка необходима? В прошлом я создавал таблицы стилей XSLT с группировкой, но мне пришлось бы немного переделать, чтобы включить группировку в эту.
4. Оси «следующий-sibling» или «предыдущий-sibling» недостаточно, потому что, например, элемент
<par>.. this is the second
по-прежнему является следующим-sibling первогоpardef
. Мы должны остановиться, когда возникает новоеpardef
. Ключ в моей группе решений по этой технологии. Также была бы истинная функция xslt 2.0xsl:for-each-group
. Много способов пойти 🙂