【问题标题】:Outputting depth of current node in the hierarchy输出层次结构中当前节点的深度
【发布时间】:2012-02-04 22:58:41
【问题描述】:

使用 XSLT/XPATH 1.0,我想创建 HTML,其中 span 元素的 class 属性指示原始 XML 层次结构中的深度。

例如,使用这个 XML 片段:

<text>
    <div type="Book" n="3">
        <div type="Chapter" n="6">
            <div type="Verse" n="12">
            </div>
        </div>
    </div>
</text>

我想要这个 HTML:

<span class="level1">Book 3</span>
<span class="level2">Chapter 6</span>
<span class="level3">Verse 12</span>

这些div 元素可以深入到什么程度尚不得而知。 divs 可以是 Book -> Chapter。它们可以是卷 -> 书 -> 章 -> 段落 -> 行。

我不能依赖@type 的值。部分或全部可能是 NULL。

【问题讨论】:

    标签: xslt xpath


    【解决方案1】:

    这有一个非常简单和简短的解决方案——没有递归,没有参数,没有xsl:element,没有xsl:attribute

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="div">
      <span class="level{count(ancestor::*)}">
       <xsl:value-of select="concat(@type, ' ', @n)"/>
      </span>
      <xsl:apply-templates/>
     </xsl:template>
    </xsl:stylesheet>
    

    当此转换应用于提供的 XML 文档时

    <text>
        <div type="Book" n="3">
            <div type="Chapter" n="6">
                <div type="Verse" n="12"></div></div></div>
    </text>
    

    产生想要的正确结果

    <span class="level1">Book 3</span>
    <span class="level2">Chapter 6</span>
    <span class="level3">Verse 12</span>
    

    说明:正确使用模板、AVT和count()函数。

    【讨论】:

      【解决方案2】:

      或者不使用递归 - 但 Dimitre 的回答比我的要好

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
      
      <xsl:template match="/text">
          <html>
              <body>
                  <xsl:apply-templates/>
              </body>
          </html>
      </xsl:template>
      
      <xsl:template match="//div">
          <xsl:variable name="depth" select="count(ancestor::*)"/>
          <xsl:if test="$depth > 0">
              <xsl:element name="span">
                  <xsl:attribute name="class">
                      <xsl:value-of select="concat('level',$depth)"/>
                  </xsl:attribute>
                  <xsl:value-of select="concat(@type, ' ' , @n)"/>
              </xsl:element>
          </xsl:if>
          <xsl:apply-templates/>
      </xsl:template>
      
      </xsl:stylesheet>
      

      【讨论】:

        【解决方案3】:

        与通常使用 XSL 一样,使用递归。

        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:output method="html" indent="yes"/>
        
          <xsl:template match="/text">
            <html>
              <xsl:apply-templates>
                <xsl:with-param name="level" select="1"/>
              </xsl:apply-templates>
            </html>
          </xsl:template>
        
        
          <xsl:template match="div">
            <xsl:param name="level"/>
        
            <span class="{concat('level',$level)}"><xsl:value-of select="@type"/> <xsl:value-of select="@n"/></span>
        
            <xsl:apply-templates>
              <xsl:with-param name="level" select="$level+1"/>
            </xsl:apply-templates>
          </xsl:template>
        
        
        </xsl:stylesheet>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-04
          • 1970-01-01
          • 1970-01-01
          • 2019-11-19
          相关资源
          最近更新 更多