2

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">
  <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 ;)

10
  • What happens if you just try "@methodname", rather than "./@methodname"? Commented Aug 9, 2010 at 14:12
  • The same, nothing... The self:node remains "stuck" a the Method element. Commented Aug 9, 2010 at 14:19
  • I think you're going to have to post a complete executable subset of the input XML and stylesheet. We appreciate you trying to reduce the problem to the minimum necessary, but I think you've reduced it too far, and the problem may be in code you didn't include. Commented Aug 9, 2010 at 14:25
  • Hmm. It was just a vague thought; I can't actually see anything greatly wrong here. As Jim says, I think we need a complete example that displays the problem. You're doing a couple of things a bit of a long way around, from what I can see, but I can't see anything that's actually wrong... Commented Aug 9, 2010 at 14:30
  • 1
    Go ahead and edit the beginning post; as long as it's basically the same question you don't need to start a new question. Commented Aug 9, 2010 at 14:41

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.