使用xslt将xhtml转换为wiki语法

时间:2009-01-22 16:29:04

标签: xslt xhtml syntax wiki

我想使用xslt 将xhtml转换为dokuwiki语法。

现在,我无法解决的一件事就是如何处理嵌套列表。 dokuwiki语法对列表项使用星号(*),每个嵌套级别(c.f。wiki syntax)前面有两个空格。

我的问题:在以下示例中,< xsl:template mach =“li”> 如何与列表项目2.1匹配。 1 要注意它的嵌套级别,以便在前面添加适量的空格?

* list item 1
* list item 2
  * list item 2.1
    * list item 2.1.1
  * list item 2.2
  * list item 2.3
* list item 3

对应

  • list item 1
  • 列表项目2
    • 列表项目2.1
      • list item 2.1.1
    • list item 2.2
    • 列表项目2.3
  • 列表项目3

以下html的显示方式如下:

<ul>
    <li>
        list item 1
    </li>
    <li>
        list item 2
        <ul>
            <li>
                list item 2.1
                <ul>
                    <li>list item 2.1.1</li>
                </ul>
            </li>
            <li>list item 2.2</li>
            <li>list item 2.3</li>
        </ul>
    </li>
    <li>
        list item 3
    </li>
</ul>

2 个答案:

答案 0 :(得分:5)

以下转型

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

 <xsl:strip-space elements="*"/>

 <xsl:variable name="vBlanks"
  select="'                                        '"/>
 <xsl:variable name="vnNestSpaces" select="2"/>


    <xsl:template match="li">
      <xsl:variable name="vNestLevel"
           select="count(ancestor::li)"/>
      <xsl:value-of select=
       "concat('&#xA;',
               substring($vBlanks,1,$vnNestSpaces*$vNestLevel),
               '*  ', normalize-space(text()[1])
               )"/>
      <xsl:apply-templates select="*"/>
    </xsl:template>
</xsl:stylesheet>

应用于原始XML文档

<ul>
    <li> list item 1
    </li>
    <li> list item 2        
        <ul>
            <li> list item 2.1                
                <ul>
                    <li>list item 2.1.1</li>
                </ul>
            </li>
            <li>list item 2.2</li>
            <li>list item 2.3</li>
        </ul>
    </li>
    <li> list item 3    </li>
</ul>

产生所需的结果

*  list item 1
*  list item 2
  *  list item 2.1
    *  list item 2.1.1
  *  list item 2.2
  *  list item 2.3
*  list item 3

请注意以下

  1. 所需的缩进由count(ancesstor::li)的值决定。

  2. 缩进的空间直接来自足够大的空白行(包含20个嵌套级别的空白)。 无需逐个递归地输出空格

  3. 转换效率更高,原因是上述2.

  4. 请注意使用XPath substring()函数。

答案 1 :(得分:2)

以下是我如何使用它:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="//li">
        <xsl:call-template name="loop">
            <xsl:with-param name="maxcount" select="count(ancestor::li)"/>
            <xsl:with-param name="initial-value" select="0"/>
        </xsl:call-template>
        <xsl:text>* </xsl:text>
        <xsl:value-of select="normalize-space(text())"/>
        <xsl:text>&#xd;</xsl:text>
        <xsl:apply-templates select="ul/li" />
    </xsl:template>
    <xsl:template name="loop">
        <xsl:param name="maxcount"/>
        <xsl:param name="initial-value"/>
        <xsl:if test="$initial-value &lt; $maxcount">
            <xsl:text>&#x9;</xsl:text>
            <xsl:call-template name="loop">
                <xsl:with-param name="maxcount" select="$maxcount"/>
                <xsl:with-param name="initial-value" select="$initial-value+1"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

以下是它如何分解:

<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

您需要确保XSLT的输出是文本,并且您还要删除任何现有的空格。

<xsl:template match="//li">
    ...
</xsl:template>

这是您的主要模板,会匹配文档中的每个<li>。此模板的第一步是输出适当数量的制表符(可随意将其调整为空格或任何您需要的)。这样做的方法是调用自定义loop模板,该模板将递归调用自身,从initial-value循环到maxcount,在每次迭代时输出制表符(&#x9;

<xsl:text>* </xsl:text>
<xsl:value-of select="normalize-space(text())"/>
<xsl:text>&#xd;</xsl:text>

此块只输出前面有*和后面有换行符(&#xd;)的文本。请注意,我使用text()函数而不是.来检索节点的值。如果不这样做,父节点的输出将(根据W3C推荐)将所有子文本节点与父节点连接起来。

<xsl:apply-templates select="ul/li" />

最后,我们以递归方式调用当前模板,但明确引用下一个<li> <ul>的{​​{1}} - 这使我们不会在同一父元素上意外调用模板两次。