开发者

Interesting XSL Dilemma

开发者 https://www.devze.com 2023-02-01 19:09 出处:网络
I\'ve got this issue. A template called \"checkbox\" that\'s called from while inside a table HTML element and also outside of it.

I've got this issue.

A template called "checkbox" that's called from while inside a table HTML element and also outside of it.

To solve an issue, I've added <td> tags to "checkbox" input control.

Here's what I'd like to do to but I'm not sure if it's possible or not.

When I hit my "row" (part of the custom table markup) template, I would set some variable or pass some parameter, that for each template applied afterwards, would know it was in a "row" and do something special based on this information. I know I can't add parameters to apply-templates. I may be able to add a row "mode" but I can't make changes to each template and have one copy with the mod parameter and one without.

Thanks for any suggestions. I know the ideal solution would to be to make changes to the XML but I'm not sure if I can do that as this point. That's a "content" issue. :P

Thanks!

Addendum:

I'm going to try to better explain my issue.

I have this template called "checkbox". Sometimes I need a tag surrounding the call that renders the checkbox, sometimes I do not. The times I do the "checkbox" template are when its parents are called by a "row" template's call to apply-templates (this translates to a , thus the need for the for the checkbox forum control).

The problem is I need to be able to reuse the c开发者_运维知识库heckbox template in both cases: 1) When it's not being called by a row template and when it IS being called by a row template.

I hope this is clearer.


You can call a template with a particular “mode”:

<xsl:apply-templates select="*" mode="row"/>

But it is also possible to apply templates with parameters:

<xsl:apply-templates select="*">
  <xsl:with-param name="mode" select="'row'"/>
</xsl:apply-templates>

The latter approach works at least if all templates that might match the elements they are applied to ('*' in this case) declare a parameter named 'mode'.


When I hit my "row" (part of the custom table markup) template, I would set some variable or pass some parameter, that for each template applied afterwards, would know it was in a "row" and do something special based on this information. I know I can't add parameters to apply-templates. I may be able to add a row "mode" but I can't make changes to each template and have one copy with the mod parameter and one without.

To begin with, parameters can be passed to templates that are selected for processing by an <xsl:apply-templates> instruction. Do read about <xsl:with-param>.

However, passing such a parameter isn't usually needed. Here is an example:

If a template matches a specific (current) node and it must act in a special way depending whether this node is within a table row, then it is a matter of a simple check:

parent::tr

selects the parent node only if it is a tr.

ancestor::tr

selects all ancestor tr nodes.

In case the first or the second XPath expressions above selects a non-empty node-set, then (respectively), the parent of the current node is a tr, or the current node is within some tr.

So, you may use an <xsl:when> to test this.

Here is how a complete solution may look like:

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

 <xsl:template match="checkbox">
  <xsl:choose>
   <xsl:when test="ancestor::tr">
     <myTag><xsl:copy-of select="."/></myTag>
   </xsl:when>
   <xsl:otherwise>
    <xsl:copy-of select="."/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document:

<t>
  <checkbox>1</checkbox>
  <table>
    <tr>
      <td><checkbox>1</checkbox></td>
    </tr>
  </table>
</t>

the wanted, correct result is produced:

<checkbox>1</checkbox>
<myTag>
   <checkbox>1</checkbox>
</myTag>

Very often conditional instructions can be completely eliminated by specifying specific templates with predicates in the match pattern. If you provide the necessary relevant information, people might be able to publish an elegant solution.


When I hit my "row" (part of the custom table markup) template, I would set some variable or pass some parameter, that for each template applied afterwards, would know it was in a "row" and do something special based on this information. I know I can't add parameters to apply-templates. I may be able to add a row "mode" but I can't make changes to each template and have one copy with the mod parameter and one without.

These are limitations of XSLT 1.0, solved in XSLT 2.0 through new mode handling and tunnel params.

In XSLT 1.0 you can have the "poor man's tunneling" overwriting the "any element" built-in rule like:

<xsl:template match="*">
   <xsl:param name="mode"/>
   <xsl:apply-templates>
      <xsl:with-param name="mode" select="$mode"/>
   </xsl:apply-templates>
</xsl:template>

Do remember to progate this pattern to your rules matching more specific elements.

0

精彩评论

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