开发者

xslt parent element position

开发者 https://www.devze.com 2023-01-11 04:24 出处:网络
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 开发者_JAVA百科position. Can

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 开发者_JAVA百科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>


This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <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.


This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <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.


0

精彩评论

暂无评论...
验证码 换一张
取 消