Xslt 将平面列表转换为嵌套列表

Xslt 将平面列表转换为嵌套列表,xslt,Xslt,我有一些描述书籍的XML,如下所示: <root> <chapter> <chapter_number>some chapter</chapter_number> <chapter_title>some title</chapter_title> <heading_1>some heading</heading_1> <

我有一些描述书籍的XML,如下所示:

<root>
    <chapter>
        <chapter_number>some chapter</chapter_number>
        <chapter_title>some title</chapter_title>

        <heading_1>some heading</heading_1>

        <para>some plain text <italic>some italic text</italic> some more text</para>

        <list_1_letter>item 1</list_1_letter>
        <list_1_letter>item 2</list_1_letter>
        <list_2_bullet>sub-item 1</list_2_bullet>
        <list_2_bullet>sub-item 2</list_2_bullet>
        <list_1_letter>item 3</list_1_letter>

        <para>some other text</para>

        <list_1_number>item 1</list_1_number>
        <list_2_roman>sub-item 1</list_2_roman>
        <list_2_roman>sub-item 2</list_2_roman>
        <list_1_number>item 2</list_1_number>
        <list_2_roman>sub-item 3</list_2_roman>
        <list_2_roman>sub-item 4</list_2_roman>
    </chapter>
</root>
列表需要包装在描述它们的元素中,但是子列表应该是它们上面的列表的子列表。在这种情况下,所需输出为:

<root>
    <chapter>
        <chapter_number>some chapter</chapter_number>
        <chapter_title>some title</chapter_title>

        <heading_1>some heading</heading_1>

        <para>some plain text <italic>some italic text</italic> some more text</para>

        <letter_list>
            <list_1_letter>item 1</list_1_letter>
            <list_1_letter>item 2</list_1_letter>
            <bullet_list>
                <list_2_bullet>sub-item 1</list_2_bullet>
                <list_2_bullet>sub-item 2</list_2_bullet>
            </bullet_list>
            <list_1_letter>item 3</list_1_letter>
        </letter_list>

        <para>some other text</para>

        <number_list>
            <list_1_number>item 1</list_1_number>
            <roman_list>
                <list_2_roman>sub-item 1</list_2_roman>
                <list_2_roman>sub-item 2</list_2_roman>
            </roman_list>
            <list_1_number>item 2</list_1_number>
            <roman_list>
                <list_2_roman>sub-item 3</list_2_roman>
                <list_2_roman>sub-item 4</list_2_roman>
            </roman_list>
        </number_list>
    </chapter>
</root>
从这里改编一些其他答案,我可以包装列表,但我只能包装相同列表的序列,它将产生:

<number_list>
    <list_1_number>item 1</list_1_number>
</number_list>
<roman_list>
    <list_2_roman>sub-item 1</list_2_roman>
    <list_2_roman>sub-item 2</list_2_roman>
</roman_list>
<number_list>
    <list_1_number>item 2</list_1_number>
</number_list>
<roman_list>
    <list_2_roman>sub-item 3</list_2_roman>
    <list_2_roman>sub-item 4</list_2_roman>
</roman_list>
不完全是我想要的!事实证明,这远比我接手这件事时预料的要狡猾

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<xsl:strip-space elements="*"/>
<xsl:output indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="*">
 <xsl:copy>
  <xsl:for-each-group select="node()" group-adjacent="starts-with(name(),'list')">
   <xsl:choose>
    <xsl:when test="current-grouping-key()">
     <xsl:element name="{replace(name(),'.*_.*_','')}_list">
      <xsl:variable name="thislist" select="name()"/>
      <xsl:for-each-group select="current-group()" group-adjacent="name()">
       <xsl:choose>
    <xsl:when test="name()=$thislist">
     <xsl:copy-of select="current-group()"/>
    </xsl:when>
    <xsl:otherwise>
     <xsl:element name="{replace(name(),'.*_.*_','')}_list">
     <xsl:copy-of select="current-group()"/>
     </xsl:element>
    </xsl:otherwise>
       </xsl:choose>
      </xsl:for-each-group>
     </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="current-group()"/>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:for-each-group>
 </xsl:copy>
</xsl:template>

</xsl:stylesheet>
产生

<root>
   <chapter>
      <chapter_number>some chapter</chapter_number>
      <chapter_title>some title</chapter_title>
      <heading_1>some heading</heading_1>
      <para>some plain text <italic>some italic text</italic> some more text</para>
      <letter_list>
         <list_1_letter>item 1</list_1_letter>
         <list_1_letter>item 2</list_1_letter>
         <bullet_list>
            <list_2_bullet>sub-item 1</list_2_bullet>
            <list_2_bullet>sub-item 2</list_2_bullet>
         </bullet_list>
         <list_1_letter>item 3</list_1_letter>
      </letter_list>
      <para>some other text</para>
      <number_list>
         <list_1_number>item 1</list_1_number>
         <roman_list>
            <list_2_roman>sub-item 1</list_2_roman>
            <list_2_roman>sub-item 2</list_2_roman>
         </roman_list>
         <list_1_number>item 2</list_1_number>
         <roman_list>
            <list_2_roman>sub-item 3</list_2_roman>
            <list_2_roman>sub-item 4</list_2_roman>
         </roman_list>
      </number_list>
   </chapter>
</root>

首先,你必须找到一条可以解释的规则。至少我不明白为什么bullet_list是字母列表的子元素,而number_list不是。你能使用XSLT 2.0吗?还是仅限于1.0?@IanRoberts我能使用XSLT 2.0@hr_117编号_列表不是字母_列表的子列表,因为它是一个完全独立的列表?标签中的数字表示其级别。list_1是一个顶级列表,list_2是list_1中的一个子列表。这非常棘手,可能XSLT不是用于此目的的最佳语言。我可以为每个组和从开始的组可视化零件解决方案,但是查找列表开始的条件不好。很明显,一个列表前面有一个非列表的东西是列表的开始,但我想你也需要发现一个列表后面紧跟着一个列表是两个独立的列表,这就是我的大脑开始融化的地方。。。使用带有可更新变量的命令式语言会容易得多。我希望有一个XSLT解决方案,但我会尝试使用Python使用lxml或其他方法,反正我在这方面有更多的经验。