tags:

views:

45

answers:

3

Hi

I have the following xml to be transformed. But I don't how to get the primary driver tag value in the transformed xml. Primary driver should be based on the driver nodes position. Can somebody help me?

<drivers>  
  <driver>  
    <first_name>Doug</first_name>  
    <last_name>Harry</last_name>  
    <vehicles>  
    <vehicle>  
    <vin>4T1BB46K08</vin>  
    <year>2008</year>  
    </vehicle>  
        </vehicles>  
        <records/>  
    </driver>  
    <driver>  
        <first_name>Sherry</first_name>  
        <last_name>Bloom</last_name>  
        <vehicles>  
            <vehicle>  
                <vin>5TDZA23C06</vin>  
                <year>2006</year>  
            </vehicle>  
        </vehicles>  
        <records/>  
    </driver>  
</drivers>

Result should be

<Vehicles>  
  <vehicle>  
    <vin>4T1BB46K08</vin>  
    <year>2008</year>  
    <primarydriver>1</primarydriver>  
  </vehicle>  
  <vehicle>  
    <vin>5TDZA23C06</vin>  
    <year>2006</year> 
    <primarydriver>2</primarydriver>  
  </vehicle>  
</Vehicles>
A: 

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="drivers">
        <Vehicles>
            <xsl:apply-templates/>
        </Vehicles>
    </xsl:template>
    <xsl:template match="driver|driver/*|driver/*/text()">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="vehicle/*[last()]">
        <xsl:call-template name="identity"/>
        <primarydriver>
            <xsl:value-of select="count(preceding::driver)+1"/>
        </primarydriver>
    </xsl:template>
</xsl:stylesheet>

Output:

<Vehicles>
    <vehicle>
        <vin>4T1BB46K08</vin>
        <year>2008</year>
        <primarydriver>1</primarydriver>
    </vehicle>
    <vehicle>
        <vin>5TDZA23C06</vin>
        <year>2006</year>
        <primarydriver>2</primarydriver>
    </vehicle>
</Vehicles>

Note: Counting preceding.

Alejandro
A: 

Hi I did this way,

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="/">
        <xsl:element name="vehicles">
            <xsl:apply-templates select="//vehicle"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="vehicle">
    <xsl:element name="vehicle">
        <xsl:variable name="VIN" select="vin"/>
        <xsl:element name="vin">
            <xsl:value-of select="$VIN"/>
        </xsl:element>
        <xsl:element name="year">
            <xsl:value-of select="year"/>
        </xsl:element>
        <xsl:for-each select="//driver">
            <xsl:if test="vehicles/vehicle[vin=$VIN]">
                <xsl:element name="PrimaryVehicleDriver">
                    <xsl:value-of select="position()"/>
                </xsl:element>
            </xsl:if>
        </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
amz
A: 

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:param name="pDriverPos"/>
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/*">
  <Vehicles>
    <xsl:apply-templates/>
  </Vehicles>
 </xsl:template>

 <xsl:template match="driver">
  <xsl:apply-templates>
   <xsl:with-param name="pDriverPos" select="position()"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="vehicles">
  <xsl:param name="pDriverPos"/>

  <xsl:apply-templates>
   <xsl:with-param name="pDriverPos" select="$pDriverPos"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="vehicle">
   <xsl:param name="pDriverPos"/>

   <vehicle>
     <xsl:apply-templates/>
     <primarydriver><xsl:value-of select="$pDriverPos"/></primarydriver>
   </vehicle>
 </xsl:template>

 <xsl:template match="first_name|last_name|records"/>
</xsl:stylesheet>

when applied on the provided XML document:

<drivers>
  <driver>
    <first_name>Doug</first_name>
    <last_name>Harry</last_name>
    <vehicles>
    <vehicle>
    <vin>4T1BB46K08</vin>
    <year>2008</year>
    </vehicle>
        </vehicles>
        <records/>
    </driver>
    <driver>
        <first_name>Sherry</first_name>
        <last_name>Bloom</last_name>
        <vehicles>
            <vehicle>
                <vin>5TDZA23C06</vin>
                <year>2006</year>
            </vehicle>
        </vehicles>
        <records/>
    </driver>
</drivers>

produces the wanted, correct result:

<Vehicles>
    <vehicle>
        <vin>4T1BB46K08</vin>
        <year>2008</year>
        <primarydriver>1</primarydriver>
    </vehicle>
    <vehicle>
        <vin>5TDZA23C06</vin>
        <year>2006</year>
        <primarydriver>2</primarydriver>
    </vehicle>
</Vehicles>

Do note: The use of a modified identity rule with a parameter that passes the current driver's position. This is significantly more efficient than counting preceding siblings.

Dimitre Novatchev