Writing a recursive function XSLT/XPath for computing new values -


i trying write recursive function computes new values. basic idea of motivates me given levels of outline, want compute new levels such numbers sequential (that is, can't go level 2 level 5) while respecting original relationships.

given input (note inputs quite different):

<root>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="4">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="8">yo</item>     <item outlinepos="8">yo</item>     <item outlinepos="9">yo</item>     <item outlinepos="3">yo</item>     <item outlinepos="8">yo</item>     <item outlinepos="4">yo</item> </root> 

i want output

<root>     <item outlinepos="0">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="0">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="2">yo</item> </root> 

i using xslt 2/xpath 2. have far not getting right results, know problem (begins fifth item in input data); i've included comments explaining i'm trying do:

<xsl:template match="@*|node()">     <xsl:copy>         <xsl:apply-templates select="@*|node()"/>     </xsl:copy> </xsl:template>  <xsl:template match="item[@outlinepos]">     <xsl:element name="item">         <xsl:attribute name="outlinepos" select="test:newlevel(.)"/>         <xsl:apply-templates select="@*[name(.)!='outlinepos'] | node()"/>     </xsl:element> </xsl:template>  <xsl:function name="test:newlevel">     <xsl:param name="context"/>     <xsl:choose>         <xsl:when test="not($context/preceding-sibling::item[1])"> <!-- if don't have preceding-sibling items, know @ level 0 -->             <xsl:sequence select="0"/> <!-- start @ 0 not 1 -->         </xsl:when>         <xsl:when test="$context/@outlinepos > $context/preceding-sibling::item[1]/@outlinepos"> <!-- if current item greater previous item, know should come after previous item find level previous item , increment 1 -->             <xsl:sequence select="test:newlevel($context/preceding-sibling::item[1])+1"/>         </xsl:when>         <xsl:when test="$context/@outlinepos = $context/preceding-sibling::item[1]/@outlinepos"> <!-- if current item equals previous item, know levels should same, need know previous level find -->             <xsl:sequence select="test:newlevel($context/preceding-sibling::item[1])"/>         </xsl:when>         <xsl:when test="$context/@outlinepos &lt; $context/preceding-sibling::item[1]/@outlinepos"> <!-- if current item less previous item, know new level depend on closest value either equal current value or less current value; if latter, need increment final result -->              <xsl:variable name="curoutlinepos" select="$context/@outlinepos"/>              <!-- next 2 variables here part doesn't work... neither computing expected values -->             <xsl:variable name="positionclosestoutlineposequals" select="count($context/preceding-sibling::item[1][(@outlinepos = $curoutlinepos)]/preceding-sibling::item)"/>             <xsl:variable name="positionclosestoutlineposlessthan" select="count($context/preceding-sibling::item[1][(@outlinepos &lt; $curoutlinepos)]/preceding-sibling::item)"/>             <xsl:message>note equals: <xsl:value-of select="$positionclosestoutlineposequals"/> less than: <xsl:value-of select="$positionclosestoutlineposlessthan"/></xsl:message>              <!-- once above variables compute right values (by selecting right nodes), we'll need update following  -->             <xsl:choose>                 <xsl:when test="$positionclosestoutlineposequals &lt; $positionclosestoutlineposlessthan">                     <xsl:sequence select="test:newlevel($context/preceding-sibling::item[1][(@outlinepos = $curoutlinepos)])"/>                 </xsl:when>                 <xsl:otherwise>                     <xsl:sequence select="test:newlevel($context/preceding-sibling::item[1][(@outlinepos &lt; $curoutlinepos)])+1"/>                 </xsl:otherwise>             </xsl:choose>         </xsl:when>         <xsl:otherwise>             <xsl:sequence select="9999998"/> <!-- testing purposes, 9999998 means "not processed", have make sure test data not use 9999998 @outlinepos value -->         </xsl:otherwise>     </xsl:choose> </xsl:function> 

any appreciated.

here simple solution:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"  xmlns:xs="http://www.w3.org/2001/xmlschema" xmlns:my="my:my">  <xsl:output omit-xml-declaration="yes" indent="yes"/>   <xsl:template match="@*|node()">     <xsl:copy>         <xsl:apply-templates select="@*|node()"/>     </xsl:copy>  </xsl:template>   <xsl:template match="@outlinepos">    <xsl:attribute name="outlinepos" select="my:level(..)"/>  </xsl:template>   <xsl:function name="my:level" as="xs:integer">   <xsl:param name="pelem" as="element()"/>    <xsl:variable name="voriglevel" select="$pelem/@outlinepos/number()"/>   <xsl:variable name="vprecedingelem" select=    "$pelem/preceding-sibling::item[@outlinepos/number() le $voriglevel][1]"/>    <xsl:sequence select=    "if(not($vprecedingelem))       0       else if($vprecedingelem/@outlinepos/number() lt $voriglevel)        my:level($vprecedingelem) +1        else if($vprecedingelem/@outlinepos/number() eq $voriglevel)          my:level($vprecedingelem)          else (: impossible happen :) -999    "/>  </xsl:function> </xsl:stylesheet> 

when transformation applied provided xml document:

<root>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="4">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="8">yo</item>     <item outlinepos="8">yo</item>     <item outlinepos="9">yo</item>     <item outlinepos="3">yo</item>     <item outlinepos="8">yo</item>     <item outlinepos="4">yo</item> </root> 

the wanted, correct result produced:

<root>     <item outlinepos="0">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="0">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="1">yo</item>     <item outlinepos="2">yo</item>     <item outlinepos="2">yo</item> </root> 

Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

CSS3 Transition to highlight new elements created in JQuery -