РЕДАКТИРОВАТЬ : Извините, я пропустил разделение текстовых узлов!
Самая общая проблема: перенос непустых строк смешанного содержимого с p
элементом
Проблема здесь в том, как поставщик входного дерева работает только с пробелами в текстовых узлах.Кажется, только Saxon сохраняет только текстовые узлы в виде пробелов ... Конечно, добавление xml:space="preserve"
во входные данные решает проблему для любого другого XSLT-процессора.
Эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:preserve-space elements="*" />
<xsl:template match="*[@html='true' or @nl2p='true']">
<div>
<xsl:apply-templates select="node()[1]"/>
</div>
</xsl:template>
<xsl:template match="node()" mode="open" name="open">
<xsl:copy-of select="." />
<xsl:apply-templates select="following-sibling::node()[1]"
mode="open" />
</xsl:template>
<xsl:template match="*[@html='true' or @nl2p='true']/node()">
<xsl:param name="pTail" select="''" />
<p>
<xsl:value-of select="$pTail" />
<xsl:call-template name="open" />
</p>
<xsl:variable name="vNext"
select="following-sibling::text()[contains(., '
')][1]" />
<xsl:apply-templates select="$vNext">
<xsl:with-param name="pString"
select="substring-after($vNext, '
')" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text()[contains(., '
')]"
mode="open" priority="1">
<xsl:value-of select="substring-before(., '
')" />
</xsl:template>
<xsl:template match="*[@html='true' or @nl2p='true']
/text()[contains(., '
')]"
priority="1" name="text">
<xsl:param name="pString" select="."/>
<xsl:choose>
<xsl:when test="contains($pString, '
')">
<xsl:variable name="vOutput"
select="normalize-space(substring-before($pString, '
'))" />
<xsl:if test="$vOutput">
<p>
<xsl:value-of select="$vOutput"/>
</p>
</xsl:if>
<xsl:call-template name="text">
<xsl:with-param name="pString"
select="substring-after($pString, '
')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="following-sibling::node()[1]">
<xsl:with-param name="pTail" select="$pString" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
С этим вводом ( более сложный, чем вопрос ):
<root>
<mixed html="true" xml:space="preserve">
line 1
line 2
<a href="http://google.com">line 2</a> after
before <em>line 3</em><img src="http://example.org"/>
</mixed>
</root>
Вывод:
<div>
<p>line 1</p>
<p>line 2</p>
<p> <a href="http://google.com">line 2</a> after</p>
<p> before <em>line 3</em><img src="http://example.org" /></p>
</div>
Уменьшение проблемы: перенос непустых строк текстовых узлов и каждого дочернего узла с p
элементом
Эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@html='true']/*">
<p>
<xsl:call-template name="identity"/>
</p>
</xsl:template>
<xsl:template match="*[@html='true']/text()" name="text">
<xsl:param name="pString" select="."/>
<xsl:choose>
<xsl:when test="contains($pString,'
')">
<xsl:call-template name="text">
<xsl:with-param name="pString"
select="substring-before($pString,'
')"/>
</xsl:call-template>
<xsl:call-template name="text">
<xsl:with-param name="pString"
select="substring-after($pString,'
')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="normalize-space($pString)">
<p>
<xsl:value-of select="normalize-space($pString)"/>
</p>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
С вводом вопросапример, вывод:
<root>
<mixed html="true">
<p>line 1</p>
<p><a href="http://google.com">line 2</a></p>
<p><em>line 3</em></p>
</mixed>
</root>
С моим более сложным входом (без @xml:space
):
<root>
<mixed html="true">
line 1
line 2
<a href="http://google.com">line 2</a> after
before <em>line 3</em><img src="http://example.org"/>
</mixed>
</root>
Выход:
<root>
<mixed html="true">
<p>line 1</p>
<p>line 2</p>
<p><a href="http://google.com">line 2</a></p>
<p>after</p>
<p>before</p>
<p><em>line 3</em></p>
<p><img src="http://example.org"></img></p>
</mixed>
</root>