Subject: RE: RE: [xsl] xsl:apply-templates with variable From: cknell@xxxxxxxxxx Date: Thu, 23 Sep 2004 13:01:42 -0400 |
It's best if we keep this thread on the list so that others might benefit from whatever solution may evolve. Please respond to the list. I'm having touble understanding why the solution I offered is unsatisfactory. The problem you have is that you wish to supply the name of a node as a parameter and use the value of that parameter to select a template match by dynamically evaluating the parameter in a select="" operation. As I said, the XSLT specification specifically prohibits this use, so you will have to find another way to do it. I suggested using an xsl:choose structure to evaluate the string value of the passed parameter and select the appropriate template to call. You replied, "I will not have any idea about the value that is being passed to me." If you knew precisely what the value of the parameter was before it was supplied, you would have no need for the parameter at all. You could simply hard-wire the transformation and be done with it. The only way that any value supplied by the parameter can be useful in this case is if matches the name of one of the elements (e.g., "CUSTOMER", "LAST_NAME", "DEPARTMENT"). Given that, you simply make one xsl:when element inside the xsl:choose for each element name that could be supplied. If you simply *must* do a dynamic evaluation, you will have to go to an extension function. The best set of these is probably EXSLT (http://www.exslt.org/dyn/index.html). Use of EXSLT and other extension functions varies with the XSL processor you are using. Since you are moving away from purse XSL, you have to be aware of the risk of non-portability in your application. -- Charles Knell cknell@xxxxxxxxxx - email -----Original Message----- From: Paria Heidari <pheidari@xxxxxxxxxxxxxx> Sent: Thu, 23 Sep 2004 11:34:46 -0400 To: <cknell@xxxxxxxxxx> Subject: RE: [xsl] xsl:apply-templates with variable Hi Charles, I am sorry that I am replying directly to you. But you were the only one who responded to my post. I will not have any idea about the value that is being passed to me. I have tried so many things and back to the first place again unsuccessful. I'll appreciate any ideas or suggestions you might have. Regards, Paria ------------------------------ Date: Tue, 21 Sep 2004 16:35:40 -0400 To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx From: cknell@xxxxxxxxxx Subject: RE: [xsl] xsl:apply-templates with variable Message-ID: <B0029234920@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> The last exception points you in the right direction. "javax.xml.transform.TransformerException: A node test that matches either NCName:* or QName was expected." The spec specifically prohibits the kind of dynamic evaluation in template matching and in XPath expressions. Michael Kay has answered this kind of question many times on this list. You might try a construct like this: <xsl:choose> <xsl:when test="$ROOT='CUSTOMER'"> <xsl:apply-templates select="CUSTOMER"/> </xsl:when> <xsl:when test="$ROOT='DEPARTMENT'"> <xsl:apply-templates select="DEPARTMENT"/> </xsl:when> <xsl:otherwise> </xsl:otherwise> </xsl:choose> -- Charles Knell cknell@xxxxxxxxxx - email --------------------------------- Date: Tue, 21 Sep 2004 16:12:27 -0400 To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx> From: "Paria Heidari" <pheidari@xxxxxxxxxxxxxx> Subject: xsl:apply-templates with variable Message-ID: <8BB65B8A64970A44B5AAA23988DC4CD6CD3AA8@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx m> Hello All, I have the following XML file: <CUSTOMERS>=09 <CUSTOMER> <CUST_ID>2</CUST_ID> <FIRST_NAME>test</FIRST_NAME> <LAST_NAME>test2</LAST_NAME> =09 <CUST_ACCUCAST_DATA> <CAD_CUST_ID>2</CAD_CUST_ID> <MSG_CONTENT>T</MSG_CONTENT> <BAD_EMAIL> </BAD_EMAIL> <USER_AGENT>Mozilla/4.0</USER_AGENT> <EMAIL_AGENT> </EMAIL_AGENT> </CUST_ACCUCAST_DATA> <DEPARTMENT> <D_ID>2</D_ID> <D_NAME>Sales</D_NAME> </DEPARTMENT> <ORDERSS> <ORDERS> <O_ID>2</O_ID> </ORDERS> </ORDERSS> </CUSTOMER> </CUSTOMERS> --------------------- with following xslt: <xsl:stylesheet version "1.0" xmlns:xsl "http://www.w3.org/1999/XSL/Transform" xmlns:fo "http://www.w3.org/1999/XSL/Format"> <xsl:param name "ROOT"/> <xsl:template match "CUSTOMERS"> =09 </xsl:template> <xsl:template match "CUSTOMER"> <xsl:call-template name "printNode"/> </xsl:template> <xsl:template name "printHeaders"> <tr bgcolor "#4D5D97"> <xsl:variable name "spanA" select "count(CUSTOMER[1]/child::*[count(child::*) 0])"/> <td colspan "{$spanA}"> <xsl:text> </xsl:text> </td> <xsl:for-each select "CUSTOMER[1]/child::*[count(child::*) > 0]"> <xsl:for-each select "child::*[1]"> <xsl:variable name "spanB" select "count(child::*)"/> <td colspan "{$spanB}" valign "top"> <font face "Arial" size "3" color "white"> <b><xsl:value-of select "name()"/></b> </font> </td> </xsl:for-each> </xsl:for-each> </tr> <tr bgcolor "#4D5D97"> <xsl:for-each select "CUSTOMER[1]/child::*[count(child::*) 0]"> <td valign "top"> <font face "Arial" size "3" color "white"> <b><xsl:value-of select "name()"/></b> </font> </td> </xsl:for-each> <xsl:for-each select "CUSTOMER[1]/child::*[count(child::*) > 0]"> <xsl:for-each select "child::*[1]"> <xsl:for-each select "child::*"> <td valign "top"> <font face "Arial" size "3" color "white"> <b><xsl:value-of select "name()"/></b> </font> </td> </xsl:for-each> </xsl:for-each> </xsl:for-each> </tr> </xsl:template> <xsl:template name "printValues"> <xsl:for-each select "child::*"> <xsl:if test "count(child::*) 0"> <td> <font face "Arial" size "3" color "black"> <xsl:value-of select "."/> </font> </td> </xsl:if> <xsl:if test "count(child::*) > 0"> <xsl:variable name "span" select "count(descendant::*)-1"/> <td colspan "{$span}" valign "top"> <table cellpadding "5" cellspacing "2" border "0" width "100%"> <xsl:for-each select "child::*"> <tr> <xsl:if test "count(child::*) 0"> <td><xsl:text> </xsl:text></td> </xsl:if> <xsl:for-each select "child::*"> <td> <font face "Arial" size "3" color "black"> <xsl:value-of select "."/> </font> </td> </xsl:for-each> </tr> </xsl:for-each> </table> </td> </xsl:if> </xsl:for-each> </xsl:template> <xsl:template name "printNode"> <tr bgcolor "#FFFFFF"> <xsl:if test "position() mod 2 0"> <xsl:attribute name "bgcolor">#E7ECF0</xsl:attribute> </xsl:if> <xsl:call-template name "printValues"/> </tr> </xsl:template> </xsl:stylesheet> ------------------- I have added the <xsl:param name "ROOT"/> and passing in this value from my Java code. This value will be a dynamic variable in my xml file. For now I am passing in CUSTOMER as the value. I print my $ROOT to make sure I have passed in the correct value. When I replace 'CUSTOMER' with ($ROOT) within my xslt file I get the following error: avax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: A node test that matches either NCName:* or QName was expected. --------------------- This is my xslt file after I replace the 'CUSTOMER' with ($ROOT) <xsl:stylesheet version "1.0" xmlns:xsl "http://www.w3.org/1999/XSL/Transform" xmlns:fo "http://www.w3.org/1999/XSL/Format"> <xsl:param name "ROOT">CUSTOMER</xsl:param> <xsl:template match "CUSTOMERS"> =09 </xsl:template> <xsl:template match "$ROOT"> <xsl:call-template name "printNode"/> </xsl:template> <xsl:template name "printHeaders"> <tr bgcolor "#4D5D97"> <xsl:variable name "spanA" select "count(($ROOT)[1]/child::*[count(child::*) 0])"/> <td colspan "{$spanA}"> <xsl:text> </xsl:text> </td> <xsl:for-each select "($ROOT)[1]/child::*[count(child::*) > 0]"> <xsl:for-each select "child::*[1]"> <xsl:variable name "spanB" select "count(child::*)"/> <td colspan "{$spanB}" valign "top"> <font face "Arial" size "3" color "white"> <b><xsl:value-of select "name()"/></b> </font> </td> </xsl:for-each> </xsl:for-each> </tr> <tr bgcolor "#4D5D97"> <xsl:for-each select "($ROOT)[1]/child::*[count(child::*) 0]"> <td valign "top"> <font face "Arial" size "3" color "white"> <b><xsl:value-of select "name()"/></b> </font> </td> </xsl:for-each> <xsl:for-each select "($ROOT)[1]/child::*[count(child::*) > 0]"> <xsl:for-each select "child::*[1]"> <xsl:for-each select "child::*"> <td valign "top"> <font face "Arial" size "3" color "white"> <b><xsl:value-of select "name()"/></b> </font> </td> </xsl:for-each> </xsl:for-each> </xsl:for-each> </tr> </xsl:template> <xsl:template name "printValues"> <xsl:for-each select "child::*"> <xsl:if test "count(child::*) 0"> <td> <font face "Arial" size "3" color "black"> <xsl:value-of select "."/> </font> </td> </xsl:if> <xsl:if test "count(child::*) > 0"> <xsl:variable name "span" select "count(descendant::*)-1"/> <td colspan "{$span}" valign "top"> <table cellpadding "5" cellspacing "2" border "0" width "100%"> <xsl:for-each select "child::*"> <tr> <xsl:if test "count(child::*) 0"> <td><xsl:text> </xsl:text></td> </xsl:if> <xsl:for-each select "child::*"> <td> <font face "Arial" size "3" color "black"> <xsl:value-of select "."/> </font> </td> </xsl:for-each> </tr> </xsl:for-each> </table> </td> </xsl:if> </xsl:for-each> </xsl:template> <xsl:template name "printNode"> <tr bgcolor "#FFFFFF"> <xsl:if test "position() mod 2 0"> <xsl:attribute name "bgcolor">#E7ECF0</xsl:attribute> </xsl:if> <xsl:call-template name "printValues"/> </tr> </xsl:template> </xsl:stylesheet> I'll appreciate any help or ideas. Many thanks in advance, Paria -- Charles Knell cknell@xxxxxxxxxx - email --+------------------------------------------------------------------ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/ or e-mail: <mailto:xsl-list-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx> --+--
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] xsl:apply-templates with , cknell | Thread | RE: RE: [xsl] xsl:apply-templates w, Paria Heidari |
[xsl] Specify/determine element's ", john-xsl-list | Date | [xsl] FYI: Announcing Saxon.NET BET, Pieter Reint Siegers |
Month |