I have to following XML document structure:
<option_set id="1">
<option>Yes</option>
<option>No</option>
<option>Maybe</option>
</option_set>
<question option_set="1">
<text>Do you like cake?</text>
</question>
<question option_set="1">
<text>Is the cake a lie?</text>
</question>
In the interests of keeping things DRY, the idea is to have a number of different questions which share common sets of options. These can then be built using XSLT. My templates are as follows:
<xsl:template match="question[@opt开发者_C百科ion_set and not(option)]">
<!-- Build a whole question with its options
(copy the options across and then apply-templates?) -->
</xsl:template>
<xsl:template match="question[option]">
<!-- Match a whole question, with options, for making pretty HTML out of -->
</xsl:template>
The idea is that once the top template has matched my question, I will be left with something that looks like the following:
<question>
<text>Do you like cake?</text>
<option>Yes</option>
<option>No</option>
<option>Maybe</option>
</question>
... Which can then be matched by the bottom template and put into my HTML document. My question is how do I create the (top) template that actually does that. I'm close, but this still isn't working:
<xsl:template match="question[@option_set and not(option)]">
<xsl:variable name="optset" select="@option_set"/>
<xsl:copy>
<xsl:copy-of select="text"/>
<xsl:copy-of select="//option_set[@id=$optset]/option"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
The transformed question block, along with its options is being copied over to the document, instead of being picked up by the top template and made into pretty HTML.
If I try to <xsl:apply-templates select="."/>
then I get caught in an infinite loop.
Not sure what you're ultimately trying to do, but this might help you.
<xsl:template match="question">
<xsl:value-of select="text"/>:
<select>
<xsl:variable name="option_set_id" select="@option_set"/>
<xsl:apply-templates select="option | //option_set[@id=$option_set_id]/option"/>
</select>
</xsl:template>
<xsl:template match="option">
<option>
<xsl:value-of select="."/>
</option>
</xsl:template>
There are tweaks, like adding the key above, and checking for unused option_sets etc. but this'll get you started.
<xsl:key name="kOptionSet" match="option_set" use="@id" />
<xsl:template match="question">
<xsl:copy>
<xsl:copy-of select="text" />
<xsl:copy-of select="key('kOptionSet', @option_set)/option" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
Should pretty much do what you want. I'm not sure why you are recursing in the first place.
精彩评论