tags:

views:

66

answers:

1

Hi all!

I've got a question about XML and XSLT:

I have this generated xml:

<?xml version="1.0"?>
<rootElement>
  <ClassSection>
    <Class name="Vehicle" base="Object">
      <isPublic />
      <isAbstract />
      <Field specifier="private" fieldType="Int32" fieldName="numberOfWheels" />
      <Field specifier="private" fieldType="Int32" fieldName="numberOfPassengers" />
      <Field specifier="private" fieldType="Int32" fieldName="totalVehicleWeight" />
      <Field specifier="private" fieldType="Int32" fieldName="emptyVehicleWeight" />
      <Field specifier="private" fieldType="String" fieldName="ownerFirstName" />
      <Field specifier="private" fieldType="String" fieldName="ownerLastName" />
      <Method specifier="public" returnType="Int32" methodName="get_TotalVehicleWeight" />
      <Method specifier="public" returnType="void" methodName="set_TotalVehicleWeight">
        <Parameter position="0" name="value" type="Int32" />
      </Method>
      <Method specifier="public" returnType="void" methodName="MovingSound">
       <isAbstract />
      </Method>
      <Method specifier="private" returnType="void" methodName="CalculateVehicleWeight" />
      <Method specifier="public" returnType="void" methodName="VehicleOwner">
        <Parameter position="0" name="firstname" type="String" />
        <Parameter position="1" name="lastName" type="String" />
      </Method>
    </Class>
    <Class name="Car" base="Vehicle">
      <isPublic />
      <isSealed />
      <Field specifier="private" fieldType="String" fieldName="brandName" />
      <Field specifier="private" fieldType="Int32" fieldName="amountOfHorsePower" />
      <Method specifier="public" returnType="void" methodName="MovingSound" />
    </Class>
    <Class name="Program" base="Object">
      <isPrivate />
    </Class>
    <Class name="Person" base="Object">
      <isPrivate />
      <Field specifier="private" fieldType="String" fieldName="firstName" />
      <Field specifier="private" fieldType="String" fieldName="lastName" />
      <Field specifier="private" fieldType="Int32" fieldName="age" />
      <Method specifier="public" returnType="String" methodName="get_FirstName" />
      <Method specifier="public" returnType="void" methodName="set_FirstName">
        <Parameter position="0" name="value" type="String" />
      </Method>
      <Method specifier="public" returnType="String" methodName="get_LastName" />
      <Method specifier="public" returnType="void" methodName="set_LastName">
        <Parameter position="0" name="value" type="String" />
      </Method>
      <Method specifier="public" returnType="Int32" methodName="get_Age" />
      <Method specifier="public" returnType="void" methodName="set_Age">
        <Parameter position="0" name="value" type="Int32" />
     </Method>
    </Class>
  </ClassSection>
  <InterfaceSection>
    <Interface name="ICar">
      <isPublic />
      <Method returnType="String" methodName="get_ShowBrandName" />
      <Method returnType="Void" methodName="set_ShowBrandName">
        <Parameter0 name="value" type="String" />
      </Method>
      <Method returnType="Void" methodName="CreateCar">
        <Parameter0 name="timeSpan" type="Int32" />
      </Method>
    </Interface>
  </InterfaceSection>
  <EnumSection>
    <Enum name="Brands">
      <EnumValues>
        <BMW />
        <MERCEDES />
        <AUDI />
      </EnumValues>
    </Enum>
  </EnumSection>
</rootElement>

This XML is output of C# reflection program. Now the goal of the XSLT transformation to generate a collection class of a given object in the XML file. I use the "Person" class for testing this since the other classes are just a bunch of weird classes made for testpurposes in previous editions of the program. So I pass on a variable which declares from which class I want to make a collection class. The name of the class I look for is passed by via a XsltArgumentList. After that the XSLT kicks in:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="text"/>
  <xsl:param name="choice"/>
  <xsl:template match="Class">
  <xsl:if test="@name = $choice">
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Collections;

  namespace CollectionClassTest001
  {
      class <xsl:value-of select="$choice"/>Collection
      {
           //Fields
           ArrayList arrayList;

           //Properties
           public int Length
           {
              get { return arrayList.Count; }
           }

           //Constructor
           public <xsl:value-of select="$choice"/>Collection()
           {
              this.arrayList = new ArrayList();
           }

           //Standard Collection functions
           public void Add<xsl:value-of select="$choice"/>(<xsl:value-of select="$choice"/> p)
           {
               arrayList.Add(p);
           }

           public void Remove<xsl:value-of select="$choice"/>(<xsl:value-of select="$choice"/> p)
           {
               arrayList.Remove(p);
           }

           <xsl:for-each select="Method">
             <xsl:apply-templates select="@specifier" /> 
             <xsl:apply-templates select="@returnType" />
             <xsl:choose>
               <xsl:when test="count(Parameter)!=0">
                 <xsl:value-of select="@methodName"/>
                 <xsl:value-of select="Parameter/@name"/>
               </xsl:when>
               <xsl:when test ="count(Parameter)=0">
                 <xsl:value-of select="@methodName"/>
               </xsl:when>
             </xsl:choose>
           </xsl:for-each>
 </xsl:if>
 </xsl:template>

 <xsl:template match="@specifier">
  <xsl:value-of select="."/>
 <xsl:text> </xsl:text>
 </xsl:template>

 <xsl:template match="@returnType">
  <xsl:value-of select="."/>
 <xsl:if test=". != 'void'">[]</xsl:if>
 <xsl:text> </xsl:text>
 </xsl:template>

 <xsl:template match="@methodName">
  <xsl:value-of select="."/>ofAll()
  {

  }
</xsl:template>
</xsl:stylesheet>

The first part of the XSLT works fine but the trouble starts at

      <xsl:when test="count(Parameter)!=0">
        <xsl:value-of select="./@methodName"/>
        <xsl:value-of select="./Parameter/@name"/>
      </xsl:when>

Entering the when clausule works but getting the values of the attribute "methodName" and "name" of the Parameter element doesn't works. When debuggin in VS2010 and hitting the first value-of statement, the debuggere states this:

self::node()  =   Method

So the current position is Method. Therefore I do not understand why "./@methodName" fails. Now I must say that I do not exactly understand the way a XML is traversed and how the current postion while traversing is dertermined.

I've tried to be as clear a possible but if information is missing, just say so!

Thanks!

P.S. I: The implementation for generating a collection class is far from finished so there are quite some things missing ;)

P.S. II: Generating a collection class is useless, I know. But hey, school comes up with the exercice, not me ;)

+1  A: 

something like this?

<xsl:variable name="className">Person</xsl:variable>

<xsl:template match="/Class">
  <xsl:if test="./@name = $className">
    <xsl:apply-templates select="./Method" />
  </xsl:if>
</xsl:template>

<xsl:template match="/Class/Method">
  <xsl:variable name="function"><xsl:apply-templates select="." mode="function" /></xsl:variable>
  <xsl:variable name="parameters"><xsl:apply-templates select="." mode="parameters" /></xsl:variable>
  <xsl:value-of select="$function" /> (<xsl:value-of select="$parameters" />)
  {
  }
</xsl:template>

<xsl:template match="/Class/Method" mode="function">
  <xsl:value-of select="./@specifier" /> <xsl:value-of select="./@returnType" /> <xsl:value-of select="./@methodName" />
</xsl:template>

<xsl:template match="/Class/Method" mode="parameters">
  <xsl:for-each select="./Parameter">
    <xsl:value-of select="./@type" /> <xsl:value-of select="./@name" /><xsl:if test="position() != last()">,</xsl:if>
  </xsl:for-each>
</xsl:template>