tags:

views:

47

answers:

2

Hey everyone,

I am trying to use <xsl:for-each select="@*"> to grab all the attributes of a given element but when i do that my <xsl:choose> statement doesn't execute.

Here is the element that I'm working with:
<textBox id="Airfare" value="" label="text 1"/>

Here is the XSLT template I'm using:

<xsl:template match="textBox">
<div>
    <xsl:choose>
        <xsl:when test="@label">
            <xsl:value-of select="@label"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>No Label Defined</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
<xsl:element name="input">
    <xsl:attribute name="type">text</xsl:attribute>
    <xsl:for-each select="@*">
        <xsl:choose>
            <xsl:when test="@id">
                <xsl:attribute name="name">form_<xsl:value-of select="@id"/></xsl:attribute>
                <xsl:attribute name="id">form_<xsl:value-of select="@id"/></xsl:attribute>
            </xsl:when>
            <xsl:when test="@label">
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="current()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:element>
</div>

And when I generate the HTML using PHP I get this:

<div>text 1<input type="text" id="Airfare" value="" label="text 1"></div>

As you can see it didn't add form_ to the id attribute it didn't generate a name attribute and it didn't skip over the label attribute.

Thanks for your help!

+1  A: 

Hi you have made 2 mistakes:

  1. testing if current attribute is wrong.The correct(in my opinion of course) is: name() = 'id'
  2. Selecting the value of current attribute should be selected using'.'

Basically in the body of the for-each loop your current element is an attribute. Which is a pair name and value. so using name() gives you the name and the value is selected by default.

 <xsl:template match="textBox">
    <div>
      <xsl:choose>
        <xsl:when test="@label">
          <xsl:value-of select="@label"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>No Label Defined</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:element name="input">
        <xsl:attribute name="type">text</xsl:attribute>
        <xsl:for-each select="@*">
          <xsl:choose>
            <xsl:when test="name() = 'id'">
              <xsl:attribute name="name">form_<xsl:value-of select="."/>
              </xsl:attribute>
              <xsl:attribute name="id">form_<xsl:value-of select="."/>
              </xsl:attribute>
            </xsl:when>
            <xsl:when test="@label">
            </xsl:when>
            <xsl:otherwise>
              <xsl:copy-of select="current()"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>
      </xsl:element>
    </div>
  </xsl:template>

I suggest you change testing conditions for the others test clauses.

P.S It depends on your xsl transformations but you would probably want to remove white spaces in creation of the new html attributes for example this one:

      <xsl:attribute name="id">
        form_<xsl:value-of select="."/>
      </xsl:attribute>

have to be:

<xsl:attribute name="name">form_<xsl:value-of select="."/>
Koynov
+2  A: 
<xsl:element name="input">       
    <xsl:attribute name="type">text</xsl:attribute>      

    <xsl:for-each select="@*">       
        <xsl:choose>       
            <xsl:when test="@id">

This tests if the current node (an attribute) has an attribute named id. Because an attribute cannot have atributes itself, the test will never succeed.

Here is a concise XSLT solution using templates, no <xsl:for-each> and no conditional logic:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vNoLabelVal" select="'No Label Defined'"/>

 <xsl:template match="textBox">
  <xsl:value-of select="concat(@label, substring($vNoLabelVal, 1 div not(@label)))"/>
  <input type="text">
    <xsl:apply-templates select="@*"/>
  </input>
 </xsl:template>

 <xsl:template match="textBox/@*">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="textBox/@id">
  <xsl:attribute name="name">
   <xsl:value-of select="concat('form_', .)"/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="textBox/@label"/>
</xsl:stylesheet>

when this transformation is applied on the given XML document:

<textBox id="Airfare" value="" label="text 1"/>

the desired, correct result is produced:

text 1<input type="text" name="form_Airfare" value="" />

when applied on this XML document (missing label attribute):

<textBox id="Airfare" value="" />

the correct result is produced:

No Label Defined<input type="text" name="form_Airfare" value="" />
Dimitre Novatchev