创建分层 xml 表单“平面"xml 类似书籍的描述 [英] Create an hierarchical xml form an "flat" xml a like book description
问题描述
这是对选择当前元素和当前元素的下一个元素之间的所有元素"提出的后续问题.即使我不确定创建一个新问题是否是正确的方法,我仍然这样做.因为原来的问题得到了回答,但后来改变了.所以在我看来,改变的问题是开放的.此外,我认为更改后的问题应该放回统计数据中,因为它适合答案.
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 < $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屋!