2016-03-03 76 views
0

從大層次結構中提取一個深度級別的智能方法是什麼?想象一下以下製表符分隔的層次文本列表:將分層文本列表轉換爲離散列表

plants 
    fruits 
     apples 
     bananas 
     cherries 
    trees 
     oaks 
     maples 
    vegetables 
     onions 
     peppers 

的目標是隻輸出與深度的一個級別的子列表:

plants 
    fruits 
    trees 
    vegetables 

fruits 
    apples 
    bananas 
    cherries 

trees 
    oaks 
    maples 

vegetables 
    onions 
    peppers 

應該在Mac上工作,並在更大/更深文件。例如,這裏有一個更大的文件:

life 
    animals 
     mammals 
      dogs 
      cats 
      rabbits 
     fish 
      salmon 
     birds 
    plants 
     fruits 
      apples 
      bananas 
      cherries 
      mangoes 
     trees 
      oaks 
      maples 
      birch 
      pine 
     vegetables 
      onions 
      peppers 

,這將是從較大的輸入輸出:

life 
    animals 
    plants 

animals 
    mammals 
    fish 
    birds 

mammals 
    dogs 
    cats 
    rabbits 

fish 
    salmon 

plants 
    fruits 
    trees 
    vegetables 

fruits 
    apples 
    bananas 
    cherries 
    mangoes 

trees 
    oaks 
    maples 
    birch 
    pine 

vegetables 
    onions 
    peppers 
+0

我添加了一個更大的例子,所以對不起現在是一個更大的問題。 –

+0

輸出順序是否重要或可以說,例如,由樹組成的塊和它的孩子來到動物塊和哺乳動物塊之間? –

+0

輸出順序無關緊要。謝謝。 –

回答

1

正如你所標記的問題作爲XSLT,我發佈一個XSLT 3.0解決方案,應該與撒克遜9.6的商業版本的工作(如例如可用氧)或撒克遜9.7或Exselt:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" 
    xmlns:mf="http://example.com/mf" 
    exclude-result-prefixes="xs math mf" 
    version="3.0"> 

<xsl:param name="text-uri" as="xs:string" select="'test2016030301.txt'"/> 

<xsl:param name="indent" as="xs:string" select="'&#9;'"/> 

<xsl:output method="text"/> 

<xsl:function name="mf:group" as="element(item)*"> 
    <xsl:param name="lines" as="xs:string*"/> 
    <xsl:param name="level" as="xs:integer"/> 
    <xsl:for-each-group select="$lines" group-starting-with=".[. instance of xs:string and matches(., '^' || string-join((1 to $level)!$indent) || '\w')]"> 
     <item data="{normalize-space()}"> 
      <xsl:sequence select="mf:group(current-group()[position() gt 1], $level + 1)"/> 
     </item> 
    </xsl:for-each-group> 
</xsl:function> 

<xsl:template name="main" match="/"> 
    <xsl:apply-templates select="mf:group(unparsed-text-lines($text-uri), 0)"/> 
</xsl:template> 

<xsl:template match="item"> 
    <xsl:value-of select="@data, */($indent || @data)" separator="&#10;"/> 
    <xsl:text>&#10;&#10;</xsl:text> 
    <xsl:apply-templates select="item[item]"/> 
</xsl:template> 
</xsl:stylesheet> 

呼叫與it:main的XSLT和文本文件的URI作爲參數text-uri