RE: RE: [xsl] xsl:apply-templates with variable

Subject: RE: RE: [xsl] xsl:apply-templates with variable
From: "Paria Heidari" <pheidari@xxxxxxxxxxxxxx>
Date: Thu, 23 Sep 2004 13:14:16 -0400
Thanks for replying.

You mention "in this case is if matches the name of one of the elements
(e.g., "CUSTOMER", "LAST_NAME", "DEPARTMENT")", however in my xml file
these values will be different. I will have no idea what to compare my
$ROOT value to. These values depend on the customer database and their
tables and fields.

You have mentioned about the extension functions. Would I be able to do
what I want by using these functions?

Thanks again for all your help,
Paria

-----Original Message-----
From: cknell@xxxxxxxxxx [mailto:cknell@xxxxxxxxxx]
Sent: Thursday, September 23, 2004 12:59 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Cc: Paria Heidari
Subject: RE: RE: [xsl] xsl:apply-templates with variable

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>
<!-- Default template match goes here -->
  </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">
    <html>
      <body>
      <table cellpadding "5" cellspacing "2" border "0"
width "100%">
=09
          <xsl:call-template name "printHeaders"/>
        <xsl:apply-templates select "CUSTOMER"/>
      </table>
      </body>
    </html>
  </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">
    <html>
      <body>
      <table cellpadding "5" cellspacing "2" border "0"
width "100%">
=09
          <xsl:call-template name "printHeaders"/>
        <xsl:apply-templates select "($ROOT)"/>
      </table>
      </body>
    </html>
  </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




--+------------------------------------------------------------------
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