我有一个原始的xml文件:
<list>
<no value="8">
<no value="11">
<no value="6">
<no value="32"/>
<no value="56"/>
</no>
<no value="9">
<no value="111"/>
<no value="67"/>
</no>
</no>
<no value="7">
<no value="5"/>
<no value="11"/>
</no>
</no>
现在我想交换父节点及其子节点的属性值,例如:
<list>
<no value="8">
<no value="11">
<no value="6">
<no value="32"/>
<no value="56"/>
</no>
<no value="9">
<no value="111"/>
<no value="67"/>
</no>
</no>
<no value="11">
<no value="5"/>
<no value="7"/>
</no>
</no>
而且我想将这个树放在一个变量中,该变量将用作另一个模板的输入源。我倾向于使用递归进行交换,直到我获得根的最大值:
<list>
<no value="111">
<no value="...">
......
</no>
有人可以给我一个建议吗?提前谢谢
答案 0 :(得分:0)
你有一个奇怪的需要...在其他语言中,二元树结构这样的东西与你的算法一起用于订购或获得最大值。这在XSLT中并不是真的需要,因为它只处理树和树,所以它有许多内置算法,如排序。
除此之外,这是我认为你想要转变的样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:param name="pReplace"/>
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:with-param name="pReplace" select="$pReplace"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="no[@value][descendant::no/@value]">
<xsl:param name="pReplace" select="''"/>
<xsl:variable name="vSwaped"
select="descendant-or-self::no
[contains($pReplace,
concat(generate-id(),
'+'))]"/>
<xsl:variable name="vPosition" select="count($vSwaped)+1"/>
<xsl:variable name="vReplace">
<xsl:for-each
select="(ancestor::no[$vSwaped]|
descendant-or-self::no)[@value]">
<xsl:sort select="@value"
data-type="number" order="descending"/>
<xsl:if test="position()=$vPosition">
<xsl:value-of select="concat(generate-id(),'+',@value)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="value">
<xsl:value-of select="substring-after($vReplace,'+')"/>
</xsl:attribute>
<xsl:apply-templates select="node()">
<xsl:with-param name="pReplace"
select="concat($pReplace,
substring-before($vReplace,'+'),
'+',generate-id(),'|')"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="no[@value][not(descendant::no/@value)]" name="find">
<xsl:param name="pReplace" select="''"/>
<xsl:param name="pFind" select="generate-id()"/>
<xsl:variable name="vFound"
select="substring-before(
substring-after(
$pReplace,
concat($pFind,'+')),
'|')"/>
<xsl:choose>
<xsl:when test="$vFound!='' and $pFind != $vFound">
<xsl:call-template name="find">
<xsl:with-param name="pReplace" select="$pReplace"/>
<xsl:with-param name="pFind" select="$vFound"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="value">
<xsl:value-of select="//no[generate-id()=$pFind]
/@value"/>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
输出:
<list>
<no value="111">
<no value="67">
<no value="56">
<no value="32"></no>
<no value="6"></no>
</no>
<no value="11">
<no value="8"></no>
<no value="9"></no>
</no>
</no>
<no value="11">
<no value="5"></no>
<no value="7"></no>
</no>
</no>
</list>
解释:父级获取其分支的第N个最大值。 N定义为其分支中已经占用的最大数量加1。如果已从其分支中取得最大值,则祖先也将进入最大计算。最后的叶子遵循替换的路径来找到它们的价值。
这更像是输入状态和输出状态之间的静态映射,除了最后一个叶子。
此外,请注意我正在使用非常一般的模式,因此只有no
个value
属性元素才会被关注。并且可以存在任何其他类型的元素,它们将被复制。