簡體   English   中英

如何使用 XSLT 將富文本 XML 列表呈現為格式良好的 HTML

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM