将分层文本列表转换为离散列表
Convert hierarchical text list to discrete lists
从大型层次结构中提取一层深度的聪明方法是什么?想象以下制表符分隔的分层文本列表:
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 和 larger/deeper 文件。例如,这是一个更大的文件:
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
由于您已将问题标记为 XSLT,我 post 一个 XSLT 3.0 解决方案应该适用于 Saxon 9.6(例如可用于 oXygen)或 Saxon 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="'	'"/>
<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=" "/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="item[item]"/>
</xsl:template>
</xsl:stylesheet>
使用 it:main
和文本文件的 URI 作为参数调用 XSLT text-uri
。
从大型层次结构中提取一层深度的聪明方法是什么?想象以下制表符分隔的分层文本列表:
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 和 larger/deeper 文件。例如,这是一个更大的文件:
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
由于您已将问题标记为 XSLT,我 post 一个 XSLT 3.0 解决方案应该适用于 Saxon 9.6(例如可用于 oXygen)或 Saxon 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="'	'"/>
<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=" "/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="item[item]"/>
</xsl:template>
</xsl:stylesheet>
使用 it:main
和文本文件的 URI 作为参数调用 XSLT text-uri
。