任意列表结构的xsl转换

时间:2010-08-28 19:18:18

标签: html xml xslt

我正在尝试转换CHM(Microsoft HTML帮助)文件索引的内容,该索引使用XSL在非常任意的HTML列表中保存结构信息(请参阅第一个代码片段 - 实际索引文件的结构有点不同,但是那里的重要部分)。我查看了几个CHM文件的索引,但 ul li 标签结构从不相同。只有一件事是静态的:有 param 标签,它们保存有关章节,部分,标题和HTML链接的信息

因此,我试图仅依靠某些 param 标签的深度信息将列表转换为XML结构(主要是转换为DocBook结构 - 请参阅第二个代码片段)

<ul>
  <li>
    <param attr="value"/>
    <ul>
      <li>
        <param attr="value"/>
        <ul>
          <li>
            <param attr="value"/>
          </li>
        </ul>
      </li>
      <li>
        <param attr="value"/>
        <ul>
          <li>
            <param attr="value"/>
          </li>
          <li>
            <param attr="value"/>
          </li>
        </ul>
      </li>
      <li>
        <param attr="value"/>
        <ul>
          <li>
            <param attr="value"/>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

我已经设法将一些索引(类似于前面的代码片段)转换为DocBook结构,但问题是我的XSL样式表不够通用。如果有人有想法将类似的HTML列表转换为DocBook结构,只使用 param标签的深度信息,请给我一些指示。

例如,深度为 X 的param标签将转换为 book 元素,深度为 X + 1 将转换为,等等 - 当然总是正确嵌套。

<book>
  <title>value1</title>
  <chapter>
    <title>value2</title>
    <section>
      <title>value3</title>
    </section>
  </chapter>
  <chapter>
    <title>value4</title>
    <section>
      <title>value5</title>
    </section>
    <section>
      <title>value6</title>
    </section>
  </chapter>
  <chapter>
    <title>value7</title>
    <section>
      <title>value8</title>
    </section>
  </chapter>
</book>

1 个答案:

答案 0 :(得分:2)

如果你的主要问题是如何根据输入树中的深度生成不同的元素,那么下面的样式表演示了一种方法:首先,通过count()元素来计算嵌套级别ancestor-or-self axis,然后使用xsl:element创建一个动态确定名称的元素。

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="li">
    <xsl:variable name="depth" select="count(ancestor-or-self::li)"/>
    <xsl:variable name="tag">
      <xsl:choose>
        <xsl:when test="$depth = 1">book</xsl:when>
        <xsl:when test="$depth = 2">chapter</xsl:when>
        <xsl:otherwise>section</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:element name="{$tag}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="param">
    <title>
      <xsl:value-of select="@attr"/>
    </title>
  </xsl:template>

</xsl:stylesheet>

编辑。这是另一种做同样的方式。这使用不同的模板来匹配不同深度的源元素。这可能更容易阅读,因为它消除了创建动态命名元素的需要。

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="li[count(ancestor-or-self::li) = 1]">
    <book>
      <xsl:apply-templates/>
    </book>
  </xsl:template>

  <xsl:template match="li[count(ancestor-or-self::li) = 2]">
    <chapter>
      <xsl:apply-templates/>
    </chapter>
  </xsl:template>

  <xsl:template match="li[count(ancestor-or-self::li) &gt; 2]">
    <section>
      <xsl:apply-templates/>
    </section>
  </xsl:template>

  <xsl:template match="param">
    <title>
      <xsl:value-of select="@attr"/>
    </title>
  </xsl:template>

</xsl:stylesheet>