使用 XSLT 对平面 XML 进行分层编号?

Hierarchical numbering of flat XML with XSLT?

我有一个平面 XML 文档,我想对其进行分层编号。这甚至可能 - <xsl:number ... count=''>?

XML-来源(部分和简化)

<modul>
  <p>
  <h1>A Heading
  <p>
  <figure>
    <img>
  <h2>A Heading
  <p>
  <h1>A Heading
  <p>
  <h2>A Heading
  <p>
  <h3>A Heading
  <p>
<modul>

期望输出 (html)

<html>
      <p>
      <h1>1. A Heading
      <p>
      <figure>
        <img>
      <h2>1.2 A Heading
      <p>
      <h1>2. A Heading
      <p>
      <h2>2.1 A Heading
      <p>
      <h3>2.1.1 A Heading
      <p>
</html>

样式表(部分)

  <xsl:template match="h1">
            <h1>
            <xsl:number count="h1"/>
                <xsl:text>. </xsl:text>
                <xsl:apply-templates/>
            </h1>
     </xsl:template>

     <xsl:template match="h2">
            <h2>
                <xsl:number count="h1 | h2" level="multiple" format="1.1.1."/>  
                <xsl:apply-templates/>  
            </h2>
     </xsl:template> 

我能够对所有 h1 和 h2 元素进行编号,但我得到的只是连续编号(所有 h 元素都是连续编号)。我无法弄清楚如何在下一级别获得 h2/h3 元素。此处是否可以进行分层编号?

我不认为你可以用 level="multiple".

我认为您可以使用

获得(比方说)h3 元素所需的数量
<xsl:template match="h3" mode="number">
  <xsl:number level="any" count="h1"/>
  <xsl:text>.</xsl:text>
  <xsl:number level="any" count="h2" from="h1"/>
  <xsl:text>.</xsl:text>
  <xsl:number level="any" count="h3" from="h2"/>
</xsl:template>

然后您可以为其他级别定义类似的模板规则,并使用 <xsl:apply-templates select="." mode="number"/>.

获取某个部分的级别编号

一些注意事项:(a) 我还没有对此进行测试,并且 (b) XSLT 1.0 中 xsl:number 的规则未指定某些情况,并且已知不同的 XSLT 1.0 实现以不同的方式解释规则。 XSLT 2.0 中的规则更加精确,并且在某些极端情况下给出的结果与 1.0 规范(的某些解读)不同。

依靠 CSS 进行编号可能会提供替代解决方案。

另一种方法是使用位置分组将平面结构转换为 HTML5 嵌套部分结构,在这种情况下,level="multiple" 解决了编号问题。

<xsl:template match="@*|node()">
       <xsl:copy>
           <xsl:apply-templates select="@*"/>
       </xsl:copy>
   </xsl:template>
    <xsl:template match="modul">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="p">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="figure">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="img">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="h1">
        <xsl:copy>
            <xsl:number count="h1" level="any" format="1"/>
            <xsl:text>. </xsl:text>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="h2">
        <xsl:copy>
            <xsl:number count="h1" level="any" format="1"/>
            <xsl:text>.</xsl:text>
            <xsl:number from="h1" count="h2" level="any"/>
            <xsl:text> </xsl:text>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="h3">
        <xsl:copy>
            <xsl:number count="h1" level="any" format="1"/>
            <xsl:text>.</xsl:text>
            <xsl:number from="h1" count="h2" level="any"/>
            <xsl:text>.</xsl:text>
            <xsl:number from="h2" count="h3" level="any"/>
            <xsl:text> </xsl:text>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

试试这个