创建分层 xml 表单“平面"xml 类似书籍的描述 [英] Create an hierarchical xml form an "flat" xml a like book description

查看:17
本文介绍了创建分层 xml 表单“平面"xml 类似书籍的描述的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是对选择当前元素和当前元素的下一个元素之间的所有元素"提出的后续问题.即使我不确定创建一个新问题是否是正确的方法,我仍然这样做.因为原来的问题得到了回答,但后来改变了.所以在我看来,改变的问题是开放的.此外,我认为更改后的问题应该放回统计数据中,因为它适合答案.

This is a following up question to question to "Select all of an element between the current element and the next of the current element". Even If I'm not sure if creating a new question is the right way I do it anyway. Because the original question was answered but changed afterwards. So in my view the changed questions is open. Also I think the changed question should be put back in the stat were it fit to the answer.

问题是如何创建分层的 xml,形成类似于书籍描述的平面"xml.

输入的xml类似于

<root>
    <heading_1>Section 1</heading_1>
    <para>...</para>
    <list_1>...</list_1>
    <heading_2>Section 1.1</heading_2>
    <para>...</para>
    <heading_3>Section 1.1.1</heading_3>
    <para>...</para>
    <list_1>...</list_1>
    <heading_2>Section 1.2</heading_2>
    <para>...</para>
    <footnote>...</footnote>
    <heading_1>Section 2</heading_1>
    <para>...</para>
    <list_1>...</list_1>
    <heading_2>Section 2.1</heading_2>
    <para>...</para>
    <list_1>...</list_1>
    <list_2>...</list_2>
    <heading_3>Seciton 2.1.1</heading_3>
    <para>...</para>
    <heading_2>Section 2.2</heading_2>
    <para>...</para>
    <footnote>...</footnote>
</root>

每个 都应该被解释为一个

的开始预期的输出 xml 是.

Each <heading_*> should be interpreted as start of an <section> The expected output xml is.

<section>
    <title>Section 1</title>
    <para>...</para>
    <list_1>...</list_1>
    <section>
        <title>Section 1.1</title>
        <para>...</para>
        <section>
            <title>Section 1.1.1</title>
            <para>...</para>
            <list_1>...</list_1>
        </section>
    </section>
    <section>
        <title>Section 1.2</title>
        <para>...</para>
        <footnote>...</footnote>
    </section>
</section>
<section>
    <title>Section 2</title>
    <para>...</para>
    <list_1>...</list_1>
    <section>
        <title>Section 2.1</title>
        <para>...</para>
        <list_1>...</list_1>
        <list_2>...</list_2>
        <section>
            <title>Section 2.1.1</title>
            <para>...</para>
        </section>
    </section>
    <section>
        <title>Section 2.2</title>
        <para>...</para>
        <footnote>...</footnote>
    </section>
</section>

我也尝试了一段时间,根据 @JLRishe 的原始解决方案找到解决方案.所以我找到了一个,并想把它放在这里作为一种可能性的答案.我希望有一个更容易理解的解决方案.

Also I tried a while to find a solution for this bases on the original solution from @JLRishe. So I found one and like to put it here as answer as one possibility. And I hope for a more comprehensible solution.

推荐答案

这里是我目前的解决方案

Here my current solution

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">

    <xsl:output method="xml" indent="yes"/>

    <xsl:variable name="headerLevel_txt">
        <heading name="__none__" level="0"/>
        <heading name="heading_1" level="1"/>
        <heading name="heading_2" level="2"/>
        <heading name="heading_3" level="3"/>
    </xsl:variable>

    <xsl:variable name="headerLevel" select="exsl:node-set($headerLevel_txt)" />


    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" >
                <xsl:with-param name="ch" select="h1" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates select="heading_1" />
        </xsl:copy>
    </xsl:template>


    <xsl:template match="heading_1 | heading_2 | heading_3" >
        <xsl:param name="previousheaader" select="'__none__'" />

        <xsl:variable name="endOfLevel" >
            <xsl:call-template name="endOfLevel">
                <xsl:with-param name="currentheaader" select="name()" />
                <xsl:with-param name="previousheaader" select="$previousheaader" />
            </xsl:call-template>
        </xsl:variable>

        <xsl:if test ="$endOfLevel != 'end'" >
            <section>
                <title>
                    <xsl:value-of select="normalize-space(.)"/>
                </title>

                <!-- following siblings including next heading  -->
                <xsl:variable name="fsinh" select="following-sibling::*[ 
                              generate-id( preceding-sibling::*
                                           [
                                             name() = 'heading_1' or name() = 'heading_2' or  name() = 'heading_3'
                                           ][1]
                                          ) = generate-id(current()) ]" />

                    <xsl:apply-templates select="$fsinh[ position()!=last()]" >
                        <xsl:with-param name="previousheaader" select="name()" />
                    </xsl:apply-templates>

                <!-- following siblings heading same as next   -->
                <xsl:variable name="fshsan" select="following-sibling::*[  
                              name() = name($fsinh[last()]) and
                              generate-id( preceding-sibling::*
                                           [
                                             name() = name(current())
                                           ][1]
                                          ) = generate-id(current()) ]" />
                <xsl:apply-templates select="$fshsan" >
                    <xsl:with-param name="previousheaader" select="name()" />
                </xsl:apply-templates>

            </section>
        </xsl:if>

    </xsl:template>

    <xsl:template name="endOfLevel">
        <xsl:param name ="currentheaader"/>
        <xsl:param name ="previousheaader"/>
        <!-- The previous heading ends if the current has an higher level (smaller level number)-->
        <xsl:variable name ="cl" select="number($headerLevel/heading[@name=$currentheaader]/@level)"/>
        <xsl:variable name ="pl" select="number($headerLevel/heading[@name=$previousheaader]/@level)"/>
        <xsl:if test ="$cl &lt; $pl">end</xsl:if>
    </xsl:template>

</xsl:stylesheet>

它将生成以下输出:

<root>
  <section>
    <title>Section 1</title>
    <para>...</para>
    <list_1>...</list_1>
    <section>
      <title>Section 1.1</title>
      <para>...</para>
      <section>
        <title>Section 1.1.1</title>
        <para>...</para>
        <list_1>...</list_1>
      </section>
    </section>
    <section>
      <title>Section 1.2</title>
      <para>...</para>
      <footnote>...</footnote>
    </section>
  </section>
  <section>
    <title>Section 2</title>
    <para>...</para>
    <list_1>...</list_1>
    <section>
      <title>Section 2.1</title>
      <para>...</para>
      <list_1>...</list_1>
      <list_2>...</list_2>
      <section>
        <title>Seciton 2.1.1</title>
        <para>...</para>
      </section>
    </section>
    <section>
      <title>Section 2.2</title>
      <para>...</para>
      <footnote>...</footnote>
    </section>
  </section>
</root>

这篇关于创建分层 xml 表单“平面"xml 类似书籍的描述的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆