Создание «оглавления» - PullRequest
       53

Создание «оглавления»

3 голосов
/ 11 апреля 2020

Рассмотрим следующий 'пример. xml'

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<level>
    <name>testA</name>
    <level>
        <name>testB</name>  
    </level>
    <level>
        <name>testC</name>  
        <level>
            <name>testD</name>  
            <level>
                <name>testE</name>  
            </level>
        </level>
    </level>
</level>
</root>

Используя xmlstarlet, я могу сделать:

xml sel -t -m //level -v name -o " " -v "count(ancestor::*)-1" -o "." -v "count(preceding-sibling::*)" -n sample.xml

Это дает:

testA 0.0
testB 1.1
testC 1.2
testD 2.1
testE 3.1

Что Должен ли я сделать, чтобы получить:

testA 0.0
testB 1.1
testC 1.2
testD 1.2.1
testE 1.2.1.1

В этом примере у меня есть только 4 уровня, но это может быть больше 4.

Я думаю о какой-то рекурсии, есть ли ссылки, которые могут объяснить, как это сделать?

1 Ответ

2 голосов
/ 13 апреля 2020

Вы должны быть в состоянии сделать это, используя XSLT с командой "tr" в xmlstarlet ...

Однако желаемый вывод немного сбивает с толку. Если «testA» - это первый уровень, и вы начинаете с нуля, почему все остальные записи не начинаются с нуля? Или, может быть, "root" должен быть равен нулю?

В любом случае, вот пример, который начинается с 1, а не с нуля, который должен помочь вам начать ...

XML Ввод (ввод. xml)

<root>
    <level>
        <name>testA</name>
        <level>
            <name>testB</name>  
        </level>
        <level>
            <name>testC</name>  
            <level>
                <name>testD</name>  
                <level>
                    <name>testE</name>  
                </level>
            </level>
        </level>
    </level>
</root>

XSLT 1.0 (test.xsl)

<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="level">
    <xsl:value-of select="concat(name, ' ')"/>
    <xsl:for-each select="ancestor-or-self::level">
      <xsl:if test="not(position()=1)">.</xsl:if>
      <xsl:number/>
    </xsl:for-each>
    <xsl:text>&#xA;</xsl:text>
    <xsl:apply-templates select="level"/>
  </xsl:template>

</xsl:stylesheet>

Командная строка

xmlstarlet tr test.xsl input.xml

Выход

testA 1
testB 1.1
testC 1.2
testD 1.2.1
testE 1.2.1.1
...