开发者

Trying to create a dynamic cascading list

So I have this data for a client ( see below ) and I want to create a bulleted list that can have any number of tiers. I also want it to be dynamic in the aspect that items can be listed more than once. The CMS is s开发者_JAVA百科et up so a TAG will claim its parents. Wherever a TAG claims its parents, its children should replicate beneath. Not sure how to tackle this with XSLT, but a simple example should end up looking something like this..

<ul>
    <li>Missions</li>
    <li>
        <ul>
            <li>Kampala, Uganda</li>
            <li>Lima, Peru</li>
        </ul>
    </li>
</ul>

If Kampala, Uganda also claimed something else as a parent, it would appear multiple times. If Kampala, Uganda had other TAGS that claimed it as a parent, these children would cascade beneath Kampala, Uganda in each instance.

<data>
<tags>
    <section id="3" handle="tags">Tags</section>
    <entry id="72">
        <parents>
            <item handle="meetings">Meetings</item>
        </parents>
        <tag handle="bible-studies">Bible studies</tag>
    </entry>
    <entry id="51">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="brazil">Brazil</tag>
    </entry>
    <entry id="31">
        <parents>
            <item handle="ministry">Ministry</item>
        </parents>
        <tag handle="childrens-ministry">Children's ministry</tag>
    </entry>
    <entry id="28">
        <parents>
            <item handle="ministry">Ministry</item>
        </parents>
        <tag handle="college-and-career-ministry">College and Career ministry</tag>
    </entry>
    <entry id="56">
        <parents>
            <item handle="the-islands-of-vanuatu">The Islands of Vanuatu</item>
        </parents>
        <tag handle="fanafo-christian-fellowship">Fanafo Christian Fellowship</tag>
    </entry>
    <entry id="29">
        <parents>
            <item handle="ministry">Ministry</item>
        </parents>
        <tag handle="high-school-ministry">High School ministry</tag>
    </entry>
    <entry id="48">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="holsbybrunn-sweden">Holsbybrunn, Sweden</tag>
    </entry>
    <entry id="22">
        <tag handle="home">Home</tag>
    </entry>
    <entry id="19">
        <tag handle="israel">Israel</tag>
    </entry>
    <entry id="30">
        <parents>
            <item handle="ministry">Ministry</item>
        </parents>
        <tag handle="junior-high-ministry">Junior High ministry</tag>
    </entry>
    <entry id="47">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="kampala-uganda">Kampala, Uganda</tag>
    </entry>
    <entry id="49">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="lima-peru">Lima, Peru</tag>
    </entry>
    <entry id="64">
        <parents>
            <item handle="" />
        </parents>
        <tag handle="meetings">Meetings</tag>
    </entry>
    <entry id="32">
        <parents>
            <item handle="ministry">Ministry</item>
        </parents>
        <tag handle="men-s-ministry">Men’s ministry</tag>
    </entry>
    <entry id="44">
        <parents>
            <item handle="" />
        </parents>
        <tag handle="ministry">Ministry</tag>
    </entry>
    <entry id="33">
        <tag handle="missions">Missions</tag>
    </entry>
    <entry id="54">
        <parents>
            <item handle="the-islands-of-vanuatu">The Islands of Vanuatu</item>
        </parents>
        <tag handle="natanara-christian-fellowship">Natanara Christian Fellowship</tag>
    </entry>
    <entry id="50">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="ouagadougou-burkina-faso">Ouagadougou, Burkina Faso</tag>
    </entry>
    <entry id="46">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="the-islands-of-vanuatu">The Islands of Vanuatu</tag>
    </entry>
    <entry id="77">
        <parents>
            <item handle="missions">Missions</item>
        </parents>
        <tag handle="villahermosa-mexico">Villahermosa, Mexico</tag>
    </entry>
    <entry id="27">
        <parents>
            <item handle="ministry">Ministry</item>
        </parents>
        <tag handle="womens-ministry">Women's ministry</tag>
    </entry>
    <entry id="73">
        <parents>
            <item handle="meetings">Meetings</item>
        </parents>
        <tag handle="worship">Worship</tag>
    </entry>
</tags>


I don't think you need the children of an item to be wrapped in another <li>.

This transformation (quite similar to that of @Alejandro, but simpler, shorter and not requiring any parameters at all):

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:key name="kChildren" match="tag"
               use="string(../parents/item/@handle)"/>

    <xsl:key name="kChildren" match="tag"
               use="../parents/item/@handle"/>

    <xsl:template match="/" name="buildChildrenList">
        <xsl:variable name="vChildren" select=
        "key('kChildren', string(@handle))"/>

        <xsl:if test="$vChildren">
            <ul>
                <xsl:apply-templates select="$vChildren"/>
            </ul>
        </xsl:if>
    </xsl:template>

    <xsl:template match="tag">
        <li>
            <xsl:value-of select="."/>
            <xsl:call-template name="buildChildrenList"/>
        </li>
    </xsl:template>
</xsl:stylesheet>

when applied on the referred to source XML document:

<data>
    <tags>
        <section id="3" handle="tags">Tags</section>
        <entry id="72">
            <parents>
                <item handle="meetings">Meetings</item>
            </parents>
            <tag handle="bible-studies">Bible studies</tag>
        </entry>
        <entry id="51">
            <parents>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="brazil">Brazil</tag>
        </entry>
        <entry id="31">
            <parents>
                <item handle="ministry">Ministry</item>
            </parents>
            <tag handle="childrens-ministry">Children's ministry</tag>
        </entry>
        <entry id="28">
            <parents>
                <item handle="ministry">Ministry</item>
            </parents>
            <tag handle="college-and-career-ministry">College and Career ministry</tag>
        </entry>
        <entry id="56">
            <parents>
                <item handle="the-islands-of-vanuatu">The Islands of Vanuatu</item>
            </parents>
            <tag handle="fanafo-christian-fellowship">Fanafo Christian Fellowship</tag>
        </entry>
        <entry id="29">
            <parents>
                <item handle="ministry">Ministry</item>
            </parents>
            <tag handle="high-school-ministry">High School ministry</tag>
        </entry>
        <entry id="48">
            <parents>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="holsbybrunn-sweden">Holsbybrunn, Sweden</tag>
        </entry>
        <entry id="22">
            <tag handle="home">Home</tag>
        </entry>
        <entry id="19">
            <tag handle="israel">Israel</tag>
        </entry>
        <entry id="30">
            <parents>
                <item handle="ministry">Ministry</item>
            </parents>
            <tag handle="junior-high-ministry">Junior High ministry</tag>
        </entry>
        <entry id="47">
            <parents>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="kampala-uganda">Kampala, Uganda</tag>
        </entry>
        <entry id="49">
            <parents>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="lima-peru">Lima, Peru</tag>
        </entry>
        <entry id="64">
            <parents>
                <item handle="" />
            </parents>
            <tag handle="meetings">Meetings</tag>
        </entry>
        <entry id="32">
            <parents>
                <item handle="ministry">Ministry</item>
            </parents>
            <tag handle="men-s-ministry">Men’s ministry</tag>
        </entry>
        <entry id="44">
            <parents>
                <item handle="" />
            </parents>
            <tag handle="ministry">Ministry</tag>
        </entry>
        <entry id="33">
            <parents>
                <item handle="" />
            </parents>
            <tag handle="missions">Missions</tag>
        </entry>
        <entry id="54">
            <parents>
                <item handle="the-islands-of-vanuatu">The Islands of Vanuatu</item>
            </parents>
            <tag handle="natanara-christian-fellowship">Natanara Christian Fellowship</tag>
        </entry>
        <entry id="50">
            <parents>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="ouagadougou-burkina-faso">Ouagadougou, Burkina Faso</tag>
        </entry>
        <entry id="46">
            <parents>
                <item handle="junior-high-ministry">Junior High ministry</item>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="the-islands-of-vanuatu">The Islands of Vanuatu</tag>
        </entry>
        <entry id="77">
            <parents>
                <item handle="missions">Missions</item>
            </parents>
            <tag handle="villahermosa-mexico">Villahermosa, Mexico</tag>
        </entry>
        <entry id="27">
            <parents>
                <item handle="ministry">Ministry</item>
            </parents>
            <tag handle="womens-ministry">Women's ministry</tag>
        </entry>
        <entry id="73">
            <parents>
                <item handle="meetings">Meetings</item>
            </parents>
            <tag handle="worship">Worship</tag>
        </entry>
    </tags>
</data>

produces the wanted, correct result:

<ul>
    <li>Home</li>
    <li>Israel</li>
    <li>Meetings
        <ul>
            <li>Bible studies</li>
            <li>Worship</li>
        </ul></li>
    <li>Ministry
        <ul>
            <li>Children's ministry</li>
            <li>College and Career ministry</li>
            <li>High School ministry</li>
            <li>Junior High ministry
                <ul>
                    <li>The Islands of Vanuatu
                        <ul>
                            <li>Fanafo Christian Fellowship</li>
                            <li>Natanara Christian Fellowship</li>
                        </ul></li>
                </ul></li>
            <li>Men’s ministry</li>
            <li>Women's ministry</li>
        </ul></li>
    <li>Missions
        <ul>
            <li>Brazil</li>
            <li>Holsbybrunn, Sweden</li>
            <li>Kampala, Uganda</li>
            <li>Lima, Peru</li>
            <li>Ouagadougou, Burkina Faso</li>
            <li>The Islands of Vanuatu
                <ul>
                    <li>Fanafo Christian Fellowship</li>
                    <li>Natanara Christian Fellowship</li>
                </ul></li>
            <li>Villahermosa, Mexico</li>
        </ul></li>
</ul>

Do note: This solution works correctly when a tag has more than one parent.

Explanation:

  1. The key:

<xsl:key name="kChildren" match="tag" use="string(../parents/item/@handle)"/>

produces all the "children" from the string value of the handle attribute of the first (only) item child of their parents sibling. This covers also such tag elements that don't have any parents sibling (in which case the key value is the empty string).

.2. A second key with the same name:

<xsl:key name="kChildren" match="tag"
           use="../parents/item/@handle"/>

matches a tag by the value of any handle attribute of the item child of their parents sibling. This makes it possible to have the tag listed for all "parents", not only for the first.

As we see here, the ability to have multiple keys with the same name is a very powerful and useful feature.


Edit: Multiple parents relationship added.

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kTagByParent"
             match="tag"
             use="../parents/item/@handle"/>
    <xsl:template match="/" name="makeUL">
        <xsl:param name="pChilds"
                   select="*/*/entry[not(parents/item/@handle!='')]/tag"/>
        <ul>
            <xsl:apply-templates select="$pChilds"/>
        </ul>
    </xsl:template>
    <xsl:template match="tag">
        <xsl:variable name="vChilds" select="key('kTagByParent',@handle)"/>
        <li>
            <xsl:value-of select="@handle"/>
        </li>
        <xsl:if test="$vChilds">
            <li>
                <xsl:call-template name="makeUL">
                    <xsl:with-param name="pChilds" select="$vChilds"/>
                </xsl:call-template>
            </li>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Output:

<ul>
    <li>home</li>
    <li>israel</li>
    <li>meetings</li>
    <li>
        <ul>
            <li>bible-studies</li>
            <li>worship</li>
        </ul>
    </li>
    <li>ministry</li>
    <li>
        <ul>
            <li>childrens-ministry</li>
            <li>college-and-career-ministry</li>
            <li>high-school-ministry</li>
            <li>junior-high-ministry</li>
            <li>men-s-ministry</li>
            <li>womens-ministry</li>
        </ul>
    </li>
    <li>missions</li>
    <li>
        <ul>
            <li>brazil</li>
            <li>holsbybrunn-sweden</li>
            <li>kampala-uganda</li>
            <li>lima-peru</li>
            <li>ouagadougou-burkina-faso</li>
            <li>the-islands-of-vanuatu</li>
            <li>
                <ul>
                    <li>fanafo-christian-fellowship</li>
                    <li>natanara-christian-fellowship</li>
                </ul>
            </li>
            <li>villahermosa-mexico</li>
        </ul>
    </li>
</ul>

With the new provided input at http://see.weareinto.com/525q , output:

<ul>
    <li>home</li>
    <li>israel</li>
    <li>meetings</li>
    <li>
        <ul>
            <li>bible-studies</li>
            <li>worship</li>
        </ul></li>
    <li>ministry</li>
    <li>
        <ul>
            <li>childrens-ministry</li>
            <li>college-and-career-ministry</li>
            <li>high-school-ministry</li>
            <li>junior-high-ministry</li>
            <li>
                <ul>
                    <li>the-islands-of-vanuatu</li>
                    <li>
                        <ul>
                            <li>fanafo-christian-fellowship</li>
                            <li>natanara-christian-fellowship</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>men-s-ministry</li>
            <li>womens-ministry</li>
        </ul></li>
    <li>missions</li>
    <li>
        <ul>
            <li>brazil</li>
            <li>holsbybrunn-sweden</li>
            <li>kampala-uganda</li>
            <li>lima-peru</li>
            <li>ouagadougou-burkina-faso</li>
            <li>the-islands-of-vanuatu</li>
            <li>
                <ul>
                    <li>fanafo-christian-fellowship</li>
                    <li>natanara-christian-fellowship</li>
                </ul>
            </li>
            <li>villahermosa-mexico</li>
        </ul>
    </li>
</ul>

Note: Node set key value, new expression to get the roots.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜