在 XSLT 中制作 ul li 结构内标题节点的目录

问题描述 投票:0回答:1

总体概述

我尝试通过仅选择标题节点(如 h1、h2…h9)来制作文档的目录 (TOC)。

这些标题节点应采用级联 

h[0-9]

-

<ul>
结构,其中依赖于
<li>
的所有
<hN+1>
都应是包含在
<hN>
<ul>
中的
<li>
示例

为了更明确,让我们看这个例子。如果我有以下文件

<hN>

document.xsl

那么预期的渲染应该是:

<?xml version="1.0" encoding="UTF-8"?> <document> <h1>Lorem <i>arepo</i> ipsum dolor</h1> <h2>Lorem ipsum dolor</h2> <p> Sed ut <i>perspiciatis</i> unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? </p> <h1>sit amet et consectetur</h1> <h2>Quia adipit</h2> <h3>aliquam quaerat</h3> <p> Sed ut <i>perspiciatis</i> unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? </p> <h2>Erit et nunquam</h2> </document>

最小工作示例

目前,我有这个

<ul> <li> <span>Lorem <i>arepo</i> ispum dolor</span> <ul> <li><span>Lorem ipsum dolor</span></li> </ul> <li> <li> <span>Sit amet et consectetur</span> <ul> <li> <span>Quia adipit</span> <ul> <li> <span>aliquam quaerat</span> </li> <ul> </li> <li><span>Erit et nunquam</span></li> </ul> <li> </ul>

maketoc.xslt

当前渲染图

但是,这个 MWE 生成以下输出:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="document"> <ul> <xsl:apply-templates select="*[self::h1 | self::h2 | self::h3 | self::h4 | self::h5 | self::h6 | self::h7 | self::h8 | self::h9]"/> </ul> </xsl:template> <xsl:template match="h1 | h2 | h3 | h4 | h5 | h6 | h7 | h8 | h9"> <li> <span><xsl:value-of select="."/></span> <ul> <xsl:apply-templates select="following-sibling::*[1][self::h1 | self::h2 | self::h3 | self::h4 | self::h5 | self::h6 | self::h7 | self::h8 | self::h9]"/> </ul> </li> </xsl:template> <!-- Ignor anything else --> <xsl:template match="*"/> </xsl:stylesheet>

存在的问题

如您所见,MWE 存在一些问题:

同一兄弟节点中的第一个降序节点会被处理多次。它们的加工程度与深度相同。例如“aliquam quaerat”出现树次,因为他是一个
    <ul> <li> <span>Lorem arepo ipsum dolor</span> <ul> <li> <span>Lorem ipsum dolor</span> <ul/> </li> </ul> </li> <li> <span>Lorem ipsum dolor</span> <ul/> </li> <li> <span>sit amet et consectetur</span> <ul> <li> <span>Quia adipit</span> <ul> <li> <span>aliquam quaerat</span> <ul/> </li> </ul> </li> </ul> </li> <li> <span>Quia adipit</span> <ul> <li> <span>aliquam quaerat</span> <ul/> </li> </ul> </li> <li> <span>aliquam quaerat</span> <ul/> </li> <li> <span>Erit et nunquam</span> <ul/> </li> </ul>
  1. 节点。
    无用的
  2. <h3>
  3. 有时会出现在内部没有任何
    </ul>
    <li>
    体内。
    不是其兄弟姐妹之间第一个的节点将被视为 
  4. <ul>
  5. 。 (参见“Erit et nunquam”的案例,他是
    <h1>
    
    
  6. 问题

如何使 xml 的标题节点位于级联

<h2>

-

<ul>
结构中,并且后代与其后代密切相关?
    

xml xslt html-lists html-heading
1个回答
0
投票
<li>

:

 进行递归分组的任务
for-each-group group-starting-with

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">
  
  <xsl:function name="mf:group" as="node()*">
    <xsl:param name="headings" as="element()*"/>
    <xsl:param name="level" as="xs:integer"/>
    <xsl:for-each-group select="$headings" group-starting-with="*[local-name() = 'h' || $level]">
      <xsl:if test="self::*[local-name() = 'h' || $level]">
        <li>
          <span>
            <xsl:apply-templates/>
          </span>
          <xsl:where-populated>
            <ul>
              <xsl:sequence select="mf:group(tail(current-group()), $level + 1)"/>
            </ul>
          </xsl:where-populated>
        </li>
      </xsl:if>
    </xsl:for-each-group>
  </xsl:function>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>
  
  <xsl:template match="document">
    <ul>
      <xsl:sequence select="mf:group(*[self::h1 | self::h2 | self::h3 | self::h4 | self::h5 | self::h6 | self::h7 | self::h8 | self::h9], 1)"/>
    </ul>
  </xsl:template>
  
</xsl:stylesheet>

有您原始代码中的选择,我可能倾向于将其写为

<xsl:sequence select="mf:group(*[self::h1 | self::h2 | self::h3 | self::h4 | self::h5 | self::h6 | self::h7 | self::h8 | self::h9], 1)"/>
    

© www.soinside.com 2019 - 2024. All rights reserved.