2009-01-22 37 views
3

我想使用xslt將xhtml轉換爲dokuwiki語法將xhtml轉換爲使用xslt的wiki語法

現在,有一件事我似乎無法處理我的頭是如何處理嵌套列表。 dokuwiki語法使用星號(*)作爲每個嵌套級別前綴兩個空格的列表項(c.f. wiki syntax)。

我的問題:在下面的例子,怎麼能<的xsl:模板馬赫=「禮」>匹配列表項目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 

對應於

  • 列表項1
  • 列表項2
    • 列表項2.1
      • 列表項2.1.1
    • 列表項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> 

回答

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()函數。

+0

+1非常好!我喜歡空白的想法 - 我知道必須有更好的方法來獲取縮進。 – 2009-01-23 02:23:50

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>的直接子 - 這讓我們意外地調用模板兩次相同的父元素。