XSLT 从段落创建列表

XSLT create list from paragraphs

我遇到了来自知名科幻出版商的 HTML 的一段,它试图使用段落作为匿名标签来模仿有序列表。示例如下:

<p class="NL1">1. first list item.</p>
<p class="NL">2. second list item.</p>
<p class="NL">3. third list item.</p>
<p class="NLL">4. last list item.</p>

我想使用 XSLT 将这个令人厌恶的东西转换成真正的有序列表。我试过的是:

    <xsl:template name="makeLi">
        <li>
            <xsl:apply-templates/>
        </li>
    </xsl:template>

    <xsl:template match="p[@class='NL1' 
        and preceding-sibling::node()[not(self::p[@class='NL1'])]]" >
        <ol>
            <xsl:call-template name="makeLi"/>
            <xsl:apply-templates select="following-sibling::node()[(self::p[@class='NL'])
                or (self::p[@class='NLL'])]"/>
        </ol>
     </xsl:template>

    <xsl:template match="p[@class='NL'
        and preceding-sibling::node()[not(self::p[@class='NL'])]
        and preceding-sibling::node()[not(self::p[@class='NL1'])]]" >
        <xsl:call-template name="makeLi"/>
    </xsl:template>

    <xsl:template match="p[@class='NLL' and preceding-sibling::node()[not(self:::p)]]" >
            <xsl:call-template name="makeLi"/>
    </xsl:template>

当我应用这个转换时,我最终得到的是:

<ol>
  <li>1. first list item.</li>
  <li>2. second list item.</li>
  <li>3. third list item.</li>
  <li>4. fourth list item.</li>
</ol>
<ul>
  <li>2. second list item.</li>
  <li>3. third list item.</li>
  <li>4. fourth list item.</li>
</ul>

如何防止“NL”和“NLL”类被二次处理?

对于 XSLT 1.0,同级递归是正确的选择,而且您的路线是正确的。未经测试,但类似这样:

<xsl:template match="p[@class='NL1']" mode="normal">
  <ol>
    <xsl:call-template name="makeLi"/>
    <xsl:apply-templates select="following-sibling::p[1]" mode="list"/>
  </ol>
</xsl:template>

<xsl:template match="p[@class='NL']" mode="list">
  <xsl:call-template name="makeLi"/>
  <xsl:apply-templates select="following-sibling::p[1]" mode="list"/>
</xsl:template>

<xsl:template match="p[@class='NLL']" mode="list">
  <xsl:call-template name="makeLi"/>
</xsl:template>

<xsl:template match="p[@class='NL' or @class='NLL']" mode="normal"/>

我为默认处理模式添加了 mode="normal" 只是为了强调,如果使用默认(未命名)模式,则应将其保留。