tags:

views:

49

answers:

6

Hi,

I'm very new to XSL and I'm having some problems.

The XML I'm using has some tags like <Example/>.

in my XSL (the output is HTML) I used something like this for tags without data:

<xsl:if test="count(ContractNr) > 0">  
  <td>Nr:</td>  
  <td><xsl:value-of select="ContractNr"/></td>  
</xsl:if>

It works great when there is no tag.

but how do I make an <xsl:if> for something like <ContractNumber/>?
Ty, and sorry for my english.

UPDATE: edited my 1 post, sorry.. what I meant was that my example works when the tag I test is not present in xml, but how do i test if the tag is "empty" like or

ty, Treemonkey, but I'm not sure if this is the solution I'm looking for.

I will try to explain better.

in the xml input file there are many tags that are "optional" or "minOccurs="0"" (according to schema). using xsl I try to make a html output with a table where I use <xsl:if> to determine if the tag is present in xml or not (no tag=no column).

I give static names to my html table columns(data in xml can not be used for nameing) and put the data from xml there. Now when the tag is <smthng/> I still get the column with the given static name - and that is the problem. I would like to make an xsl:if so that if there is a <smthng/> the column is not made:

<table>
  <tr><xsl:if ...>
    <td>Some name:</td>
    <td><xsl:value-of select="smthng"/></td></xsl:if>
  </tr>
</table>
A: 

Isn't <ContractNumber></ContractNumber> the same as <ContractNumber/>?

See the XML reference: http://www.w3.org/TR/xml/#sec-starttags

Casey
A: 

I edited my 1 post, sorry.. what I meant was that my <xsl:if> example works when the tag I test is not present in xml, but how do i test if the tag is "empty" like <smthng/> or <smthng></smthng>

ty, Treemonkey, but I'm not sure if this is the solution I'm looking for.

I will try to explain better.

in the xml input file there are many tags that are "optional" or "minOccurs="0"" (according to schema). using xsl I try to make a html output with a table where I use <xsl:if> to determine if the tag is present in xml or not (no tag=no column).
I give static names to my html table columns(data in xml can not be used for nameing) and put the data from xml there. Now when the tag is <smthng/> I still get the column with the given static name - and that is the problem. I would like to make an xsl:if so that if there is a <smthng/> the column is not made:
<table>
<tr><xsl:if ...>
<td>Some name:</td>
<td><xsl:value-of select="smthng"/></td></xsl:if>
</tr>
</table>

Jonas
A: 

Is this what your looking for? This will check for the element then allow you to use the name of the node, using the local-name() function

this also answers your second question using the apply templates for the node will only apply a template to matching elements so works much the same as an IF as naturally if there is not a match nothing will happen!

<xsl:template match="/">
<xsl:apply-templates select="ContractNumber"/>
</xsl:template>

<xsl:template match="ContractNumber">
<div>
<xsl:value-of select="local-name()"/>
</div>
</xsl:template>

you could use the following

<xsl:if test="ContractNumber=''"> do stuff </xsl:if>

or

<xsl:choose>
<xsl:when test="ContractNumber=''">
   <!--do nothing-->
</xsl:when>
<xsl:otherwise>
   <!--build table -->
</xsl:otherwise>
</xsl:choose>
Treemonkey
+1  A: 
<xsl:if test="count(ContractNr) &gt; 0">
  <td>Nr:</td>
  <td><xsl:value-of select="ContractNr"/></td>
</xsl:if>

This is bad XSLT.

Better use:

<xsl:apply-templates select="ContractNr[1]"/>

and have a separate template:

<xsl:template match="ContractNr/text()">
 <td>Nr:</td>
 <td><xsl:value-of select="."/></td>
</xsl:template>

The lesson to learn: XSLT pattern matching makes unnecessary a great deal of conditional logic that is "typical" for other programming languages.

Dimitre Novatchev
A: 

tried the <xsl:choose> solution, but it doesn't work..am I doing it wrong?

               <xsl:choose>
                    <xsl:when test="PRNumber=''">
                    </xsl:when>
                    <xsl:otherwise>
                    <tr>

                        <td>Nr:</td>
                        <td>
                            <xsl:value-of select="PRNumber"/>
                        </td>
                    </tr>
                    </xsl:otherwise>
                </xsl:choose>

in the output I still get row and "NR:" column when the XML has <PRNumber/>

Jonas
A: 

Two solutions for what I think it's what you want.

With this input:

<table>
   <row>
      <a>A1</a>
      <b>B1</b>
      <c>C1</c>
   </row>
   <row>
      <a>A2</a>
      <b>B2</b>
   </row>
   <row>
      <a>A3</a>
      <b/>
      <c>C3</c>
   </row>
</table>

This stylesheet:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:h="header"
 exclude-result-prefixes="h">
    <h:header title="First" element="a"/>
    <h:header title="Second" element="b"/>
    <h:header title="Third" element="c"/>
    <xsl:template match="table">
        <html>
            <table style="border:1px solid black;">
                <tr>
                    <xsl:apply-templates select="document('')/*/h:*"
                     mode="header"/>
                </tr>
                <xsl:apply-templates/>
            </table>
        </html>
    </xsl:template>
    <xsl:template match="row">
        <tr>
            <xsl:apply-templates select="document('')/*/h:*">
                <xsl:with-param name="pContext" select="."/>
            </xsl:apply-templates>
        </tr>
    </xsl:template>
    <xsl:template match="h:*">
        <xsl:param name="pContext"/>
        <td>
            <xsl:value-of select="$pContext/*[name()=current()/@element]"/>
        </td>
    </xsl:template>
    <xsl:template match="h:*" mode="header">
        <th>
            <xsl:value-of select="@title"/>
        </th>
    </xsl:template>
</xsl:stylesheet>

Output:

<html>
    <table style="border:1px solid black;">
        <tr>
            <th>First</th>
            <th>Second</th>
            <th>Third</th>
        </tr>
        <tr>
            <td>A1</td>
            <td>B1</td>
            <td>C1</td>
        </tr>
        <tr>
            <td>A2</td>
            <td>B2</td>
            <td></td>
        </tr>
        <tr>
            <td>A3</td>
            <td></td>
            <td>C3</td>
        </tr>
    </table>
</html>

And this other stylesheet:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:h="header"
 exclude-result-prefixes="h">
    <h:header title="First" element="a"/>
    <h:header title="Second" element="b"/>
    <h:header title="Third" element="c"/>
    <xsl:template match="table">
        <html>
            <xsl:apply-templates/>
        </html>
    </xsl:template>
    <xsl:template match="row">
        <table style="border:1px solid black;">
            <xsl:apply-templates select="document('')/*/h:*">
                <xsl:with-param name="pContext" select="."/>
            </xsl:apply-templates>
        </table>
    </xsl:template>
    <xsl:template match="h:*">
        <xsl:param name="pContext"/>
        <tr>
            <th>
                <xsl:value-of select="@title"/>
            </th>
            <td>
                <xsl:value-of select="$pContext/*[name()=current()/@element]"/>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

Output:

<html>
    <table style="border:1px solid black;">
        <tr>
            <th>First</th>
            <td>A1</td>
        </tr>
        <tr>
            <th>Second</th>
            <td>B1</td>
        </tr>
        <tr>
            <th>Third</th>
            <td>C1</td>
        </tr>
    </table>
    <table style="border:1px solid black;">
        <tr>
            <th>First</th>
            <td>A2</td>
        </tr>
        <tr>
            <th>Second</th>
            <td>B2</td>
        </tr>
        <tr>
            <th>Third</th>
            <td></td>
        </tr>
    </table>
    <table style="border:1px solid black;">
        <tr>
            <th>First</th>
            <td>A3</td>
        </tr>
        <tr>
            <th>Second</th>
            <td></td>
        </tr>
        <tr>
            <th>Third</th>
            <td>C3</td>
        </tr>
    </table>
</html>

Note: I think you are ussing row headers because the problem with empty or not present elements. Do note the use of inline mapping (It could be within other input source) for header name and column order (wether present or not).

Alejandro