开发者

XSLT apply-templates recursiveness of doom!

开发者 https://www.devze.com 2023-03-05 07:09 出处:网络
I have to following XML document structure: <option_set id=\"1\"> <option>Yes</option>

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.

0

精彩评论

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

关注公众号