【问题标题】:Hierarchical numbering of flat XML with XSLT?使用 XSLT 对平面 XML 进行分层编号?
【发布时间】:2018-05-12 20:43:21
【问题描述】:

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

XML-Source(部分和简化)

<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 元素。这里可以分层编号吗?

【问题讨论】:

    标签: xml xslt numbers hierarchical flat


    【解决方案1】:

    我认为你不能使用 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>
    

    然后您可以为其他级别定义类似的模板规则,并使用&lt;xsl:apply-templates select="." mode="number"/&gt; 获取某个部分的级别编号。

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

    依靠 CSS 进行编号可能会提供另一种解决方案。

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

    【讨论】:

    • 这行得通。通过一些小的调整,我能够将它合并到我的样式表中。另一种方法是将平面 XML 转换为层次结构,也是一种选择,但我将其放在列表的末尾。顺便说一句,我几天前订购了你的“程序员参考”,现在我正在等待它的到来:)。很高兴在这里结识您的“熟人”。
    【解决方案2】:
    <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>
    

    试试这个

    【讨论】:

    • 据我所知,这与上面的答案相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-25
    相关资源
    最近更新 更多