If I have a simple XML document of
<albums>
<album name="Napoleon Bonaparte" artist="male" year="1993" genre="rock">
<song title="test" track="1"/>
<song title="test4" track="2"/>
<song title="test6" track="3"/>
</album>
<album name="Cleopatra" artist="female" year="1993" genre="jazz">
<song title="test1" track="1"/>
<song title="test2" track="2"/>
<song title="test3" track="3"/>
</album>
</albums>
And a template that is
<box id="albumList" orient="vertical" datasources="list.xml" ref="*" querytype="xml">
<template>
<query expr="*" />
<action>
<box uri="?" align="left" class="album" orient="vertical">
<box flex="1">
<description class="albumName" value=开发者_StackOverflow社区"?name"/>
<label class="albumArtist" value="?artist"/>
</box>
<listbox class="songlist" align="left" collapsed="true">
<listitem uri="?" label="?title"/>
</listbox>
</box>
</action>
</template>
</box>
How can I get the <listbox>
element to properly display the title of each song beneath the album name? The album name/artist display fine, but I can't figure out how to structure the XML query to target the song
children of album.
That's a pretty tricky question, thank you for asking. Using recursive templates documentation provides some clues but seems to be missing an important part. Here is what works in the end:
<vbox id="albumList" datasources="list.xml" ref="*" querytype="xml">
<template>
<query expr="album|song">
<assign var="?type" expr="local-name(.)"/>
</query>
<rule>
<where subject="?type" rel="equals" value="album"/>
<action>
<vbox uri="?" align="left" class="album">
<vbox flex="1">
<description class="albumName" value="?name"/>
<label class="albumArtist" value="?artist"/>
</vbox>
<listbox uri="?" class="songlist" align="left"/>
</vbox>
</action>
</rule>
<rule parent="listbox">
<where subject="?type" rel="equals" value="song"/>
<action>
<listitem uri="?" label="?title"/>
</action>
</rule>
</template>
</vbox>
As suggested by the documentation, this assigns the XML tag name to the ?type
variable and uses it to generate different content for album
and song
tags (via <rule>
and <where>
). Note uri="?"
on the <listbox>
tag, it designates that tag as the point where the generated content for the child tags need to be inserted. But the template engine will additionally insert content for the child tags directly into the content of the parent tag - this is prevented by the parent="listbox"
restriction on the rule for songs. I changed the query expression to album|song
to make sure that other tags are immediately ignored but this is not strictly necessary.
A side-note: normally the <box>
tag isn't used. The <hbox>
and <vbox>
tags are preferred since they don't require you to specify content orientation separately.
精彩评论