[英]How to render richtext XML lists as well-formed HTML using XSLT
我有從舊版 Lotus Notes 應用程序中提取並嵌入了富文本格式的 XML 數據。 我在將富文本列表呈現為格式良好的 HTML 時遇到了困難。
問題是每個列表都沒有結束標記來指示列表何時結束。 但是,每個列表都有一個帶有唯一 ID 的開始標記,用於指示列表的開頭,並且每個列表項都有一個與列表 ID 匹配的屬性。 富文本有很多噪音(垃圾段落),通常散布在合法的列表項之間,需要忽略。
我的 XSLT 靈感來自 @Tim-C 的這個解決方案,但它不起作用。
這是 XML:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="NoBullet6.xslt"?>
<document>
<item name="Unordered list">
<richtext>
<pardef/>
<par def="20">
<run>This is the first </run>
<run>paragraph of the preamble.</run>
</par>
<par>
<run>This is the second paragraph of the </run>
<run>preamble.</run>
</par>
<pardef id="21" list="unordered"/>
<par def="21">
<run>This is the </run>
<run>first bullet.</run>
</par>
<par def="20">
<run/>
<!-- This is an empty paragraph/garbage data -->
</par>
<par>
<run>This is the second </run>
<run>bullet.</run>
</par>
<par def="20">
<run>This is the first </run>
<run>paragraph of the conclusion.</run>
</par>
<par>
<run>This is the second paragraph of the </run>
<run>conclusion.</run>
</par>
</richtext>
</item>
<item name="Ordered list">
<richtext>
<pardef/>
<par def="20">
<run>This is the first </run>
<run>paragraph of the preamble.</run>
</par>
<par>
<run>This is the second paragraph of the </run>
<run>preamble.</run>
</par>
<pardef id="46" list="ordered"/>
<par def="46">
<run>This is the </run>
<run>first numbered item.</run>
</par>
<par def="47">
<run/>
<!-- This is an empty paragraph/garbage data -->
</par>
<par def="46">
<run>This is the another </run>
<run>numbered item.</run>
</par>
<par def="20">
<run>This is the first </run>
<run>paragraph of the conclusion.</run>
</par>
<par>
<run>This is the second paragraph of the </run>
<run>conclusion.</run>
</par>
</richtext>
</item>
</document>
這是所需的輸出:
<html>
<body>
<table border="1">
<tr>
<td>Unordered list</td>
<td>
<p>This is the first paragraph of the preamble.</p>
<p>This is the second paragraph of the preamble.</p>
<ul>
<li>This is the first bullet.</li>
<li>This is the second bullet.</li>
</ul>
<p>This is the first paragraph of the conclusion.</p>
<p>This is the second paragraph of the conclusion.</p>
</td>
</tr>
<tr>
<td>Ordered list</td>
<td>
<p>This is the first paragraph of the preamble.</p>
<p>This is the second paragraph of the preamble.</p>
<ol>
<li>This is the first numbered item.</li>
<li>This is the another numbered item.</li>
</ol>
<p>This is the first paragraph of the conclusion.</p>
<p>This is the second paragraph of the conclusion.</p>
</td>
</tr>
</table>
</body>
這是 XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:key name="pars" match="par[not(@def)]" use="generate-id(preceding-sibling::par[@def][1])" />
<xsl:template match="/*">
<html>
<body>
<table border="1">
<xsl:apply-templates />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<tr>
<td><xsl:value-of select="@name"/></td>
<td>
<xsl:apply-templates select="richtext/par[@def]" />
</td>
</tr>
</xsl:template>
<xsl:template match="par[@def]">
<xsl:variable name="listType" select="preceding-sibling::*[1][self::pardef]/@list" />
<xsl:variable name="group" select="self::* | key('pars', generate-id())" />
<xsl:choose>
<xsl:when test="$listType = 'unordered'">
<ul>
<xsl:apply-templates select="$group" mode="list"/>
</ul>
</xsl:when>
<xsl:when test="$listType = 'ordered'">
<ol>
<xsl:apply-templates select="$group" mode="list"/>
</ol>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="$group" mode="para" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="par" mode="list">
<li>
<xsl:value-of select="run" separator=""/>
</li>
</xsl:template>
<xsl:template match="par" mode="para">
<p>
<xsl:value-of select="run" separator=""/>
</p>
</xsl:template>
</xsl:stylesheet>
當您使用 XSLT 2.0 時,您實際上可以在這里使用xsl:for-each-group
,這可能會簡化事情。
你能基的par
可以通過元件def
屬性(忽略“空”的元素),或在不存在的情況下def
屬性,但def
第一前(非空)的兄弟姐妹的一個屬性。
<xsl:for-each-group select="par[run[normalize-space()]]"
group-adjacent="if (@def) then @def else preceding-sibling::par[run[normalize-space()]][@def][1]/@def">
您可以使用函數current-group()
來獲取當前組,而不是groups
變量。
試試這個 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<html>
<body>
<table border="1">
<xsl:apply-templates />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<tr>
<td><xsl:value-of select="@name"/></td>
<td>
<xsl:apply-templates select="richtext" />
</td>
</tr>
</xsl:template>
<xsl:template match="richtext">
<xsl:for-each-group select="par[run[normalize-space()]]" group-adjacent="if (@def) then @def else preceding-sibling::par[run[normalize-space()]][@def][1]/@def">
<xsl:variable name="listType" select="preceding-sibling::*[1][self::pardef]/@list" />
<xsl:choose>
<xsl:when test="$listType = 'unordered'">
<ul>
<xsl:apply-templates select="current-group()" mode="list"/>
</ul>
</xsl:when>
<xsl:when test="$listType = 'ordered'">
<ol>
<xsl:apply-templates select="current-group()" mode="list"/>
</ol>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="para" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="par" mode="list">
<li>
<xsl:value-of select="run" separator=""/>
</li>
</xsl:template>
<xsl:template match="par" mode="para">
<p>
<xsl:value-of select="run" separator=""/>
</p>
</xsl:template>
</xsl:stylesheet>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.