我有以下问题。我在解决方案上工作了两天但我找不到一个。
我有一个不常见的level-attribute列表(列表只用GDocs中的边距表示),我想重新整理(排序)节点而不重构XML。
我的意见:
<lists>
<list margin="10">1</list>
<list margin="15">2</list>
<somethingelse/>
<list margin="33">3</list>
<list margin="72">4</list>
<list margin="15">5</list>
<list margin="64">6</list>
<list margin="72">7</list>
</lists>
这个输出没问题:
<lists>
<list level="1">1</list>
<list level="2">2</list>
<somethingelse/>
<list level="1">3</list>
<list level="3">4</list>
<list level="1">5</list>
<list level="2">6</list>
<list level="3">7</list>
</lists>
我想要的输出(两个节点之间的电平差异应该只有1)
<lists>
<list level="1">1</list>
<list level="2">2</list>
<somethingelse/>
<list level="1">3</list>
<list level="2">4</list>
<list level="1">5</list>
<list level="2">6</list>
<list level="3">7</list>
</lists>
这也可以用XSLT 1.0吗?
答案 0 :(得分:0)
我似乎自己回答了我的问题。这是解决方案。请记住,两个列表之间的级别差异最大为+ -1。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- copy all other nodes -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!-- find every list element which has a preceding non-list element -->
<xsl:template match="list[not(preceding-sibling::*[1][self::list])]">
<!-- now walk recursive through all lists -->
<xsl:apply-templates select="self::list" mode="recurse">
<xsl:with-param name="level1_margin" select="@margin"/>
<xsl:with-param name="level" select="1"/>
</xsl:apply-templates>
</xsl:template>
<!-- remove other list elements, because they are recursive processed -->
<xsl:template match="list"/>
<!-- remove @margin from list -->
<xsl:template match="list/@margin"/>
<!-- go recursive through all following lists -->
<xsl:template match="list" mode="recurse">
<xsl:param name="level1_margin" select="0"/>
<xsl:param name="level" select="1"/>
<xsl:variable name="nextStep" select="self::list/following-sibling::*[1][self::list]"/>
<!-- create current list element with its level -->
<xsl:apply-templates select="self::list" mode="create">
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
<xsl:if test="$nextStep">
<xsl:choose>
<!-- new start margin/point for level 1 -->
<xsl:when test="($nextStep/@margin <= $level1_margin) or ($nextStep/@margin < @margin and $level = 2)">
<xsl:apply-templates select="$nextStep" mode="recurse">
<xsl:with-param name="level1_margin" select="$nextStep/@margin"/>
<xsl:with-param name="level" select="1"/>
</xsl:apply-templates>
</xsl:when>
<!-- -1 -->
<xsl:when test="$nextStep/@margin < @margin and $level > 1">
<xsl:apply-templates select="$nextStep" mode="recurse">
<xsl:with-param name="level1_margin" select="$level1_margin"/>
<xsl:with-param name="level" select="$level - 1"/>
</xsl:apply-templates>
</xsl:when>
<!-- +1 -->
<xsl:when test="$nextStep/@margin > @margin">
<xsl:apply-templates select="$nextStep" mode="recurse">
<xsl:with-param name="level1_margin" select="$level1_margin"/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:apply-templates>
</xsl:when>
<!-- +-0 -->
<xsl:otherwise>
<xsl:apply-templates select="$nextStep" mode="recurse">
<xsl:with-param name="level1_margin" select="$level1_margin"/>
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<!-- create list element with level attribute -->
<xsl:template match="list" mode="create">
<xsl:param name="level"/>
<list>
<xsl:attribute name="level">
<xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</list>
</xsl:template>