Мне нужно создать неупорядоченные списки HTML из плоской структуры XML, используя XSLT 1.0.Входной XML состоит из серии узлов, которые должны быть преобразованы в элементы списка.Тем не менее, эта серия может быть прервана не перечисленными узлами разных типов:
<input>
<paragraph>abc</paragraph>
<paragraph>def</paragraph>
<listable>123</listable>
<listable>456</listable>
<other-block>
<other-text>Foo</other-text>
</other-block>
<listable>789</listable>
<listable>012</listable>
</input>
Моя цель:
<div class="output">
<p>abc</p>
<p>def</p>
<ul>
<li>123</li>
<li>456</li>
</ul>
<div class="my-block">
<p class="other">Foo</p>
</div>
<ul>
<li>789</li>
<li>012</li>
</ul>
</div>
Я нашел старый поток с решением, котороеу меня почти работает (последнее решение на странице, Димитр Новатчев) и адаптировал его.Это минимальная таблица стилей, основанная на этом решении:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- IDENTITY TRANSFORM: -->
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- NON-LIST ITEMS: -->
<xsl:template match="input">
<div class="output">
<xsl:apply-templates />
</div>
</xsl:template>
<xsl:template match="paragraph">
<p>
<xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="other-block">
<div class="my-block">
<xsl:apply-templates select="descendant::other-text" />
</div>
</xsl:template>
<xsl:template match="other-text">
<p class="other">
<xsl:copy-of select="text()" />
</p>
</xsl:template>
<!-- LIST HANDLING: -->
<xsl:key name="kFollowingUL" match="listable"
use="generate-id(preceding-sibling::*[not(self::listable)][1])"/>
<xsl:template match="*[not(self::listable) and following-sibling::*[1][self::listable]]">
<xsl:call-template name="identity" />
<xsl:variable name="vFolUL"
select="key('kFollowingUL',generate-id())"/>
<xsl:if test="$vFolUL">
<ul>
<xsl:apply-templates mode="copy"
select="key('kFollowingUL',generate-id())" />
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="listable" mode="copy">
<li>
<xsl:value-of select="normalize-space()" />
</li>
</xsl:template>
<xsl:template match="listable" />
</xsl:stylesheet>
Проблема этого подхода заключается в том, что он не применяет преобразования к последнему неперечисляемому узлу перед каждым списком.Узлы <paragraph>
и <other-block>
во входе копируются непосредственно в выход, хотя шаблоны применяются к потомкам <other-block>
:
<div class="output">
<p>abc</p>
<paragraph>def</paragraph>
<ul>
<li>123</li>
<li>456</li>
</ul>
<other-block>
<p class="other">Foo</p>
</other-block>
<ul>
<li>789</li>
<li>012</li>
</ul>
</div>
Может кто-нибудь предложить способ изменить более раннюю версию XSLT 1.0решение и добавить преобразование последних узлов перед списочными группами?