2013-05-14 115 views
2

我正在使用XSLT將用作文檔集的TOC的XML文件轉換爲Excel可以分隔的格式。例如,在Excel中打開時,限定版本可能看起來像:XSLT for循環並找到具有最多祖先的節點

+-----------+---------------+------+-----------+---------------------+ 
|URL  |Title   |Depth |Level 1 |Level 2    | 
+-----------+---------------+------+-----------+---------------------+ 
|dogs.html |Dogs are cool |2  |Animals |Domesticated Animals | 
+-----------+---------------+------+-----------+---------------------+ 

這部分我已經工作了,我會在下面顯示的示例代碼。

我的問題是,我想在每個級別的列標題頂部插入列標題。目前,我手動執行此操作,但是我想對具有不同級別的多個文檔集進行轉換。

所以我的問題是如何找出什麼級別的最高數量(即哪個節點擁有最多的祖先)並創建多個列標題?

下面是示例XML:

<contents Url="toc_animals.html" Title="Animals"> 
<contents Url="toc_apes.html" Title="Apes"> 
    <contents Url="chimps.html" Title="Some Stuff About Chimps" /> 
</contents> 
<contents Url="toc_cats" Title="Cats"> 
    <contents Url="hairless_cats.html" Title="OMG Where Did the Hair Go?"/> 
    <contents Url="wild_cats.html" Title="These Things Frighten Me"/> 
</contents> 
<contents Url="toc_dogs.html" Title="Dogs"> 
    <contents Url="toc_snorty_dogs.html" Title="Snorty Dogs"> 
     <contents Url="boston_terriers.html" Title="Boston Terriers" /> 
     <contents Url="french_bull_dogs.html" Title="Frenchies" /> 
    </contents> 
</contents> 
</contents> 

這裏是XSLT:

<?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" indent="no"/> 

<!-- This variable sets the delimiter symbol that Excel will use to seperate the cells --> 
<xsl:variable name="delimiter">@</xsl:variable> 

<xsl:template match="contents"> 

    <!-- Prints the URL --> 
    <xsl:value-of select="@Url"/> 
    <xsl:copy-of select="$delimiter" /> 

    <!-- Prints the title --> 
    <xsl:apply-templates select="@Title"/> 
    <xsl:copy-of select="$delimiter" /> 

    <!-- Prints the depth--i.e., the number of categories, sub-categories, etc. --> 
    <xsl:value-of select="count(ancestor::*[@Title])"/> 
    <xsl:copy-of select="$delimiter" /> 

    <!-- Sets up the categories --> 
    <xsl:for-each select="ancestor::*[@Title]"> 
     <xsl:apply-templates select="@Title"/> 
     <xsl:if test="position() != last()"> 
      <xsl:copy-of select="$delimiter" /> 
     </xsl:if> 
    </xsl:for-each> 
    <xsl:text>&#xA;</xsl:text> 
</xsl:template> 

<xsl:template match="/"> 

    <!-- Creates the column headings manually --> 
    <xsl:text>URL</xsl:text> 
    <xsl:copy-of select="$delimiter" /> 
    <xsl:text>Title</xsl:text> 
    <xsl:copy-of select="$delimiter" /> 
    <xsl:text>Depth</xsl:text> 
    <xsl:copy-of select="$delimiter" /> 
    <xsl:text>Level 1</xsl:text> 
    <xsl:copy-of select="$delimiter" /> 
    <xsl:text>Level 2</xsl:text> 
    <xsl:copy-of select="$delimiter" /> 
    <xsl:text>&#xA;</xsl:text> 

    <xsl:apply-templates select="//contents"/> 
</xsl:template> 

</xsl:stylesheet> 

回答

0

最大的東西(祖先計數,在這種情況下)是很容易選擇的。按降序排列該質量,將第一個值存儲到變量中。

<xsl:variable name="levels"> 
    <xsl:for-each select="//contents[not(*)]"> 
    <xsl:sort select="count(ancestor::*)" data-type="number" order="descending" /> 
    <xsl:if test="position() = 1"> 
     <xsl:value-of select="count(ancestor::*)" /> 
    </xsl:if> 
    </xsl:for-each> 
</xsl:variable> 

但你是不是在真正感興趣,你有興趣的標題:

<xsl:for-each select="//contents[not(*)]"> 
    <xsl:sort select="count(ancestor::*)" data-type="number" order="descending" /> 
    <xsl:if test="position() = 1"> 
    <xsl:for-each select="ancestor::*"> 
     <!-- one header for each ancestor of the most deeply nested node --> 
     <xsl:value-of select="concat('Level ', position())" /> 
     <xsl:choose> 
     <xsl:when test="position() = last()"> 
      <xsl:text>&#xA;</xsl:text> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$delimiter" /> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
    </xsl:if> 
</xsl:for-each> 
+0

工作就像一個魅力!非常感謝你的幫助! – mrthetooth

+0

不客氣。完美的第一次問題,順便說一句。足夠的代碼樣本,很好的解釋,格式良好,簡潔。 – Tomalak