如何使用xslt从平面html创建嵌套菜单

时间:2015-01-27 18:35:25

标签: php xml xslt

我有这个HTML

<h1>Index</h1>
<p>some content</p>
<p>some more content</p>
<h1>Tema</h1>
<p>some content</p>
<p>other content</p>
<h2>Sección</h2>
<p>some content</p>
<p>other content</p>
<h2>Unidad</h2>
<p>some content</p>
<p>other content</p>

使用这个,我必须创建一个如下所示的嵌套菜单(没有注释,这些仅仅是解释性的):

  <div id="siteNav">
    <ul>
      <li>
        <a href="index.html" class="daddy">
          Index <!-- H1 -->
        </a></li>
      <li>
        <a href="tema.html" class="daddy">
          Tema  <!-- H1 -->
        </a>
        <ul>
          <li>
            <a href="seccion.html" class="daddy">
               Sección <!-- H2 -->
            </a>
            <ul>
              <li id="active">
                <a href="unidad.html" class="no-ch">
                  Unidad <!-- H3 -->
                </a>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </div>

我的部分解决方案是使用PHP修改html以对标题进行分组:

<div class='menu'>
  <h1>Index</h1>
  <p>some content</p>
  <p>some more content</p>
</div>
<div class='menu'> 
  <h1>Tema</h1>
  <p>some content</p>
  <p>other content</p>
    <div class='menu2'> 
      <h2>
         ...
      </h2>
    </div>
</div>

然后应用以下xsl模板:

<xsl:template match="/">
    <ul>
        <xsl:apply-templates/>  
    </ul>
</xsl:template>

<xsl:template match="div[@class='menu']">
    <li>
        <xsl:if test="count(div[@class='menu2']) &gt; 0">
            <xsl:attribute name='class'>
                daddy
            </xsl:attribute>
            <xsl:value-of select='h1' />
        </xsl:if>

        <xsl:if test="count(div[@class='menu2']) &gt; 0">
            <ul class='other-section'><xsl:apply-templates select="div[@class='menu2']"/></ul>
        </xsl:if>
    </li>
</xsl:template>

<xsl:template match="div[@class='menu2']">
    <li>
        <a>
            <xsl:attribute name='href'>
                <xsl:value-of select="concat(translate(h2, 'áéíóú ', 'aeiou-'),'.html')" />
            </xsl:attribute>
            <xsl:value-of select='h2'/>
        </a> 
    </li>
</xsl:template>

是否有纯XSLT 1.0方法可以做到这一点?

1 个答案:

答案 0 :(得分:2)

如果 - 且仅当 - 您的输入HTML文档也是格式良好的XML文档,例如:

<html>
    <h1>Index</h1>
    <p>some content</p>
    <p>some more content</p>
    <h1>Tema</h1>
    <p>some content</p>
    <p>other content</p>
    <h2>Sección</h2>
    <p>some content</p>
    <p>other content</p>
    <h2>Unidad</h2>
    <p>some content</p>
    <p>other content</p>
</html>

然后你可以使用像这样的样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="h2" match="h2" use="generate-id(preceding-sibling::h1[1])" />

<xsl:template match="/html">
    <div id="siteNav">
        <ul>
            <xsl:apply-templates select="h1"/>
        </ul>
    </div>
</xsl:template>

<xsl:template match="h1 | h2">
    <li>
        <a href="{.}.html" class="{local-name()}">
          <xsl:value-of select="."/>
        </a>
        <xsl:variable name="h2" select="key('h2', generate-id())" />       
        <xsl:if test="$h2">
            <ul>
                <xsl:apply-templates select="$h2"/>
            </ul>
        </xsl:if>
    </li>
</xsl:template>

</xsl:stylesheet>

接收以下输出

<div id="siteNav">
  <ul>
    <li>
      <a href="Index.html" class="h1">Index</a>
    </li>
    <li>
      <a href="Tema.html" class="h1">Tema</a>
      <ul>
        <li>
          <a href="Sección.html" class="h2">Sección</a>
        </li>
        <li>
          <a href="Unidad.html" class="h2">Unidad</a>
        </li>
      </ul>
    </li>
  </ul>
</div>