xml - How can I use XSLT to permutate a node hierarchy, part 2 -


this question extends previous question.

in previous question asked how permutate node hierarchy in tree of fixed depth. example every leaf path /x/y/z wanted leaf in output have path y/x/z. (permutation 2,1,3).

instead of handling fixed-length permutations, want permutations "2,1, 3..n-1"

so xslt looks this:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/>  <xsl:template match="/input">     <output>         <xsl:apply-templates select="text()"/>     </output> </xsl:template>      <!-- example 2,1,3:n -->      <xsl:template match="text()">         <xsl:variable name="n" select="5" /> <!-- should later depth of leaf -->         <xsl:element name="{name(ancestor::*[2])}"> <!-- 2 -->             <xsl:element name="{name(ancestor::*[1])}"> <!-- 1 -->                 <xsl:call-template name="loop"> <!-- 3:5 -->                     <xsl:with-param name="i" select="3" />                     <xsl:with-param name="end" select="$n - 1" />                 </xsl:call-template>             </xsl:element>         </xsl:element>     </xsl:template>       <xsl:template name="loop">         <xsl:param name="i" />         <xsl:param name="end" />          <xsl:choose>             <xsl:when test="$i = $end">                     <xsl:copy-of select="."/>             </xsl:when>             <xsl:otherwise>                 <xsl:element name="{name(ancestor::*[$i])}">                     <!-- recursive call -->                     <xsl:call-template name="loop">                         <xsl:with-param name="i" select="$i+1" />                         <xsl:with-param name="end" select="$end" />                     </xsl:call-template>                  </xsl:element>             </xsl:otherwise>         </xsl:choose>     </xsl:template>  </xsl:stylesheet> 

i'm not sure if recursive use of templates work theoretically. on right track?

i believe generic solution this:

xslt 1.0

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/>  <xsl:template match="/*">     <output>         <xsl:apply-templates select="//text()"/>     </output> </xsl:template>  <xsl:template match="text()">     <xsl:call-template name="re-order">         <xsl:with-param name="node-set" select="ancestor::*|." />         <xsl:with-param name="order">2,1,3,</xsl:with-param>     </xsl:call-template> </xsl:template>   <xsl:template name="re-order">     <xsl:param name="node-set" />     <xsl:param name="order" />     <xsl:param name="i" select="1" />      <xsl:variable name="n" select="count($node-set)" />     <xsl:variable name="p">         <xsl:choose>             <xsl:when test="$order">                 <xsl:value-of select="substring-before($order, ',')" />             </xsl:when>             <xsl:otherwise>                 <xsl:value-of select="$i" />             </xsl:otherwise>         </xsl:choose>     </xsl:variable>      <xsl:choose>         <xsl:when test="$i &lt; $n">             <xsl:element name="{name($node-set[number($p)])}">                 <!-- recursive call -->                 <xsl:call-template name="re-order">                     <xsl:with-param name="node-set" select="$node-set" />                     <xsl:with-param name="order" select="substring-after($order, ',')" />                     <xsl:with-param name="i" select="$i + 1" />                 </xsl:call-template>             </xsl:element>         </xsl:when>         <xsl:otherwise>             <xsl:copy-of select="$node-set[last()]"/>         </xsl:otherwise>     </xsl:choose> </xsl:template>  </xsl:stylesheet> 

test input:

<one>     <two>         <three>3.1</three>         <three>3.2</three>     </two>     <two>         <three>             <four>4.1</four>             <four>4.2</four>         </three>         <three>             <four>                 <five>5.1</five>                 <five>5.2</five>             </four>             <four>                 <five>5.3</five>                 <five>5.4</five>             </four>         </three>     </two>     <two>          <three>             <four>                 <five>                     <six>6.1</six>                     <six>6.2</six>                 </five>             </four>         </three>     </two>     <two>2.1</two>     <two>2.2</two> </one> 

result:

<?xml version="1.0" encoding="utf-8"?> <output>    <two>       <one>          <three>3.1</three>       </one>    </two>    <two>       <one>          <three>3.2</three>       </one>    </two>    <two>       <one>          <three>             <four>4.1</four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>4.2</four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>                <five>5.1</five>             </four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>                <five>5.2</five>             </four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>                <five>5.3</five>             </four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>                <five>5.4</five>             </four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>                <five>                   <six>6.1</six>                </five>             </four>          </three>       </one>    </two>    <two>       <one>          <three>             <four>                <five>                   <six>6.2</six>                </five>             </four>          </three>       </one>    </two>    <two>       <one>2.1</one>    </two>    <two>       <one>2.2</one>    </two> </output> 

notes:

  1. by default, root element included top-most ancestor of leaf text node (you can override when calling template fist time);
  2. it assumed depth of leaf text node no less number of tokens in $order parameter; otherwise may unexpected results.

Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - .htaccess mod_rewrite for dynamic url which has domain names -

Website Login Issue developed in magento -