xslt - Merging two Sequences in xsl -


  • 2 sequences of elements sorted increasing. , xsl outputs 1 sequence containing items , sorted them increasingly.

input:

<!doctype lists system "list.dtd">  <numbers> <list>    <num val="2"/>    <num val="5"/>    <num val="8"/>    <num val="12"/>    <num val="20"/>    <num val="32"/> </list> <list>    <num val="4"/>    <num val="7"/>    <num val="10"/>    <num val="29"/>    <num val="30"/> </list> </numbers> 

the output should be:

<?xml version="1.0" encoding="utf-8"?>  <!doctype lists system "list.dtd"> <numbers> <list>    <num val="2"/>    <num val="4"/>    <num val="5"/>    <num val="7"/>    <num val="8"/>    <num val="10"/>    <num val="12"/>    <num val="20"/>    <num val="29"/>    <num val="30"/>    <num val="32"/> </list> </numbers> 

here xsl ,the result wrong ,could show me??

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:xs="http://www.w3.org/2001/xmlschema" exclude-result-prefixes="xs">   <xsl:output method="xml"  version="1.0" encoding="utf-8" indent ="yes"/>  <xsl:template match="/"> <xsl:apply-templates/>  <xsl:text>&#10;</xsl:text>  </xsl:template>   <xsl:template match="lists">   <xsl:copy>   <list>     <xsl:call-template name="merge">       <xsl:with-param name ="num1" select="list[1]/item" as="element(item)*"/>       <xsl:with-param name="num2" select ="list[2]/item" as="element(item)*"/>     </xsl:call-template>    </list>   </xsl:copy> </xsl:template>  <xsl:template name="merge" as="element(item)*"> <xsl:param name="num1" as="element(item)*"/> <xsl:param name="num2" as="element(item)*"/> <xsl:choose>   <xsl:when test="empty($num1)">     <xsl:sequence select="$num2"/>   </xsl:when>   <xsl:when test="empty($num2)">     <xsl:sequence select="$num1"/>    </xsl:when>       <xsl:when test="$num2[1]/@val ge $num1[1]/@val">       <xsl:sequence select="$num1[1]"/>       <xsl:call-template name="merge">         <xsl:with-param name="num1"  select="$num1[position()>1]"/>         <xsl:with-param name="num2" select="$num2[1]"/>       </xsl:call-template>     </xsl:when>       <xsl:otherwise>         <xsl:sequence select="$num2[1]"/>         <xsl:call-template name="merge">           <xsl:with-param name="num1" select="$num1[1]"/>           <xsl:with-param name="num2"  select="$num2[position()>1]"/>         </xsl:call-template>       </xsl:otherwise>     </xsl:choose>   </xsl:template> </xsl:transform> 

    <?xml version="1.0" encoding="utf-8"?>     <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform"         version="1.0">     <xsl:output indent="yes"/>      <xsl:template match="numbers">         <xsl:copy>          <list>             <!--process of num elements -->             <xsl:apply-templates select="list/num">             <!--sort num elements @val, number ensure proper sort order-->                 <xsl:sort select="number(@val)"/>             </xsl:apply-templates>          </list>         </xsl:copy>     </xsl:template>      <!--identity template - copies content forward default -->         <xsl:template match="@*|node()">             <xsl:copy>                 <xsl:apply-templates select="@*|node()" />             </xsl:copy>         </xsl:template>      </xsl:stylesheet> 

if don't want use xsl:sort, , want use stylesheet , custom "merge" template, there couple of adjustments need make in order work sample input. below corrected version inline comments explaining adjustments made:

<xsl:transform version="2.0"     xmlns:xsl="http://www.w3.org/1999/xsl/transform"     xmlns:xs="http://www.w3.org/2001/xmlschema" exclude-result-prefixes="xs">      <xsl:output method="xml"  version="1.0" encoding="utf-8" indent ="yes"/>      <xsl:template match="/">         <xsl:apply-templates/>         <xsl:text>&#10;</xsl:text>     </xsl:template>      <!--issue#1: matching on "lists" -->     <xsl:template match="numbers">         <xsl:copy>             <list>                 <xsl:call-template name="merge">                     <!--issue#2: these parameters restricted "item", not "num" -->                     <xsl:with-param name ="num1" select="list[1]/num" as="element(num)*"/>                     <xsl:with-param name="num2" select ="list[2]/num" as="element(num)*"/>                 </xsl:call-template>             </list>         </xsl:copy>     </xsl:template>      <!--issue#3: these output restricted "item", not "num" -->     <xsl:template name="merge" as="element(num)*">         <!--issue#4: these parameters restricted "item", not "num" -->         <xsl:param name="num1" as="element(num)*"/>         <xsl:param name="num2" as="element(num)*"/>          <xsl:choose>             <xsl:when test="empty($num1)">                 <xsl:sequence select="$num2"/>             </xsl:when>             <xsl:when test="empty($num2)">                 <xsl:sequence select="$num1"/>             </xsl:when>             <!--issue#5: these values need evaluated numbers, string compare give bad results(e.g. "10" less "8") -->             <xsl:when test="number($num2[1]/@val) ge number($num1[1]/@val)">                  <xsl:sequence select="$num1[1]"/>                 <xsl:call-template name="merge">                     <xsl:with-param name="num1"  select="$num1[position()>1]"/>                     <xsl:with-param name="num2" select="$num2"/>                 </xsl:call-template>             </xsl:when>             <xsl:otherwise>                 <xsl:sequence select="$num2[1]"/>                 <xsl:call-template name="merge">                     <xsl:with-param name="num1" select="$num1"/>                     <xsl:with-param name="num2"  select="$num2[position()>1]"/>                 </xsl:call-template>             </xsl:otherwise>          </xsl:choose>     </xsl:template> </xsl:transform> 

Comments