我有一个递归节点,我正在尝试为jquery-checktree设置。节点看起来像
foo/bar/ID
/NAME
/CHECKED
bar/ID
/NAME
/CHECKED
/bar/ID
/NAME
/bar/ID
/NAME
/bar/ID
/NAME
/CHECKED
/bar/ID
/NAME
/CHECKED
如果任何栏可能有或没有一个或多个栏位节点,但任何栏都有ID和NAME,可能有CHECKED。
我希望将其转变为
<ul>
<li><input type="checkbox" name="..." value="..." checked="checked"></input>
<label for="...">...</label>
<ul>
<li><input type="checkbox" name="..." value="..." checked="checked"></input>
<label for="...">...</label>
</li>
</ul>
<li>....</li>
</ul>
我可以通过以下方式获得第一级:
<ul class="tree">
<xsl:for-each select="/foo/bar/">
<li><input type="checkbox" name="{ID}" value="{ID}">
<xsl:if test="CHECKED = 'Y'"><xsl:attribute name="checked">checked</xsl:attribute></xsl:if>
</input><label for="{ID}"><xsl:value-of select="NAME"/></label>
</li>
</xsl:for-each>
</ul>
但是我不知道如何递归到“bar”中的嵌入式“bar”,可能会有很多级别。
答案 0 :(得分:5)
这是一种方式:
<xsl:template match="bar">
<li>
<input type="checkbox" name="{ID}" value="{ID}">
<xsl:if test="CHECKED = 'Y'">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:if>
</input>
<label for="{ID}"><xsl:value-of select="NAME"/></label>
<!--
If we have bar children, make a list and recurse
-->
<xsl:if test="bar">
<ul>
<xsl:apply-templates select="bar"/>
</ul>
</xsl:if>
</li>
</xsl:template>
这依赖于“自动”模板匹配。为确保匹配发生,您可以在原始代码的<xsl:apply-templates/>
循环中放置<xsl:for-each>
,但是,您甚至可以改进所有内容并使用此模板替换原始代码:
<xsl:template match="/foo">
<ul class="tree">
<xsl:apply-templates select="bar"/>
</ul>
</xsl:template>
如果您想要更多控制权,还可以使用<xsl:for-each select="bar">
并在循环内调用命名模板(<xsl:template name="some-name">...
和<xsl:call-template>
)。请参阅:http://www.w3.org/TR/xslt#named-templates
答案 1 :(得分:3)
这是一个完全由输入驱动的推式解决方案(仅模板匹配,无条件,无命名模板)的示例(实际上是概念证明):
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="*[bar]">
<ul class="tree">
<xsl:apply-templates select="bar" mode="li" />
</ul>
</xsl:template>
<xsl:template match="bar" mode="li">
<li>
<xsl:apply-templates select="." mode="checkbox" />
<xsl:apply-templates select="(.)[bar]" />
</li>
</xsl:template>
<xsl:template match="bar" mode="checkbox">
<input type="checkbox" id="{ID}" name="{NAME}">
<xsl:apply-templates select="CHECKED" />
</input>
<label for="{ID}">
<xsl:value-of select="NAME" />
</label>
</xsl:template>
<xsl:template match="CHECKED">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
当应用于此输入XML时(根据您的问题推断):
<foo>
<bar>
<ID>nd1</ID>
<NAME>Node 1</NAME>
<CHECKED />
<bar>
<ID>nd2</ID>
<NAME>Node 2</NAME>
<CHECKED />
</bar>
</bar>
<bar>
<ID>nd3</ID>
<NAME>Node 3</NAME>
</bar>
<bar>
<ID>nd4</ID>
<NAME>Node 4</NAME>
<bar>
<ID>nd5</ID>
<NAME>Node 5</NAME>
<CHECKED />
<bar>
<ID>nd6</ID>
<NAME>Node 6</NAME>
<CHECKED />
</bar>
</bar>
</bar>
</foo>
它产生这个输出:
<ul class="tree">
<li>
<input type="checkbox" id="nd1" name="Node 1" checked="checked" />
<label for="nd1">Node 1</label>
<ul class="tree">
<li>
<input type="checkbox" id="nd2" name="Node 2" checked="checked" />
<label for="nd2">Node 2</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="nd3" name="Node 3" />
<label for="nd3">Node 3</label>
</li>
<li>
<input type="checkbox" id="nd4" name="Node 4" />
<label for="nd4">Node 4</label>
<ul class="tree">
<li>
<input type="checkbox" id="nd5" name="Node 5" checked="checked" />
<label for="nd5">Node 5</label>
<ul class="tree">
<li>
<input type="checkbox" id="nd6" name="Node 6" checked="checked" />
<label for="nd6">Node 6</label>
</li>
</ul>
</li>
</ul>
</li>
</ul>
答案 2 :(得分:2)
<xsl:template match="foo">
<ul class="tree">
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="bar" name="wunderbar">
<!-- we want to match all bars, not only /foo/bars -->
<li>
<input type="checkbox" name="{ID}" value="{ID}">
<xsl:if test="CHECKED = 'Y'"><xsl:attribute name="checked">checked</xsl:attribute></xsl:if>
</input><label for="{ID}">
<xsl:value-of select="NAME"/>
</label>
<!-- If there is some bar, the next template is applied -->
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template match="bar/bar">
<!-- Just adds <ul> around bar included in bar and calls the usual template -->
<ul>
<xsl:call-template name="wunderbar"/>
</ul>
</xsl:template>