Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old February 24th, 2010, 06:01 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default Attributes - Output only if they exist

Hi Everyone,

How do you only output an attribute if it exists? For example, if you have a table and a row element that can contain 0-3 attributes:

<table>
<row backgroundcolor="#ccc">
<data>row one</data>
</row>
<row backgroundcolor="00f" text-align="center">
<data>row one</data>
</row>
<row backgroundcolor="00f" text-align="center" text-weight="bold">
<data>row one</data>
</row>
</table>

I know how to output the attributes, something like the following block (outputting an html table row element):

<xsl:for-each select="row">
<tr bgcolor="{@background-color}" align="{@text-align}" style="font-weight:{@text-weight}">

The problem is that this will output empty attributes if the attribute doesn't exist in the source xml, and the processor I'm using will throw warnings if there are empty attributes. I've used <choose> blocks to test if an attribute exists and then outputting it if it does exist, but this can become really messy with nested <choose> blocks if there are many attributes.

So my question is, how would experienced xslt users approach this problem? How would you only output an attribute if it exists? Is there a simple check that one can do other than nesting a bunch of <choose> blocks?


Thanks,
Josh
 
Old February 24th, 2010, 07:26 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Good question.

If the attribute name and value are the same in the input and output, I would use <xsl:copy-of select="@x"/>, which outputs nothing if @x is absent.

If the name or value are different, I would probably use <xsl:apply-templates select="@*"/>, with template rules like

Code:
<xsl:template match="@background-color">
  <xsl:attribute name="bgcolor" select="."/>
</xsl:template>
(the select attribute of xsl:attribute is 2.0 only: in 1.0, use a nested xsl:value-of).
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old February 25th, 2010, 12:18 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

In my project the attribute names and values are the same in the input and output, so I could use <xsl:copy-of select="@*"/>. I'm not clear how to use the xsl:copy-of element properly, however. How do I get the values that it grabs into my <tr> element? If I use the same for-each block as in my example, where do I put the copy-of, and how do I get the values into the <tr> element? I'm thinking something like the following, but I'm still unsure how to get the values into the <tr>:

<xsl:for-each select="row">
<xsl:copy-of select="@*"/>
<tr ???>



Thanks,
Josh
 
Old February 25th, 2010, 12:22 PM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Code:
<xsl:for-each select="row">
  <tr>
    <xsl:copy-of select="@*"/>
  </tr>
</xsl:for-each>
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old February 25th, 2010, 02:16 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks for the reply. This works great, and simplifies my code significantly. I'm not sure I understand how this is working--I guess I never expected the xsl:copy-of statement to insert the attributes in the previous <tr> element. If anyone cares to explain the logic behind this I would love to hear it.

At any rate, thanks for the help. This was exactly what I was looking for.


Thanks,
Josh
 
Old February 25th, 2010, 03:05 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Quote:
Originally Posted by JoshC View Post
Thanks for the reply. This works great, and simplifies my code significantly. I'm not sure I understand how this is working--I guess I never expected the xsl:copy-of statement to insert the attributes in the previous <tr> element. If anyone cares to explain the logic behind this I would love to hear it.
The xsl:copy-of is a child of that literal result 'tr' element and that way it adds nodes to that 'tr' result element, in the case of xsl:copy-of select="@*" it adds attribute nodes to the 'tr' element.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old February 25th, 2010, 08:14 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

For the semantics of this, see the section "Constructing Complex Content" in the XSLT 2.0 spec. Within a literal result element like <tr>...</tr>, there's a sequence of instructions (called a "sequence constructor"). These instructions are evaluated to create (usually) a sequence of nodes, typically some attribute nodes and then some elements and/or text nodes. The attributes become attributes of the new (tr) element, the elements become its children. You can also of course create the attributes using logic such as

Code:
<tr>
  <xsl:if test="condition">
     <xsl:attribute name="valign" select="'top'"/>
  </xsl:if>
  <td>...</td>
</tr>
but in this case xsl:copy-of is easier.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
Does Example for Fig 8-2 exist tomschiff BOOK: Professional Microsoft SQL Server 2008 Reporting Services ISBN: 978-0-470-24201-8 1 October 14th, 2009 09:06 AM
If Exist then Update Neal SQL Server 2000 4 July 25th, 2007 07:49 AM
if an attribute exist kgoldvas XSLT 4 July 4th, 2007 07:24 AM
Table Exist? elansolutionsltd Access VBA 5 January 23rd, 2006 03:43 AM
Copying Source Node attributes to output node pvsat XSLT 2 November 3rd, 2005 09:46 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.