xml - XSLT for loop and find the node with the most ancestors -


i'm using xslt transform xml file used toc documentation set format excel can delimit. example, when opened in excel, delimited version might like:

+-----------+---------------+------+-----------+---------------------+ |url        |title          |depth |level 1    |level 2              | +-----------+---------------+------+-----------+---------------------+ |dogs.html  |dogs cool  |2     |animals    |domesticated animals | +-----------+---------------+------+-----------+---------------------+ 

this part have worked out, , i'll show sample code below.

my problem i'd insert column headers @ top column header each level. currently, manually, want use transform on multiple doc sets varying number of levels.

so question how find out highest number of levels (i.e., node has ancestors) , create many column headers?

here sample xml:

<contents url="toc_animals.html" title="animals"> <contents url="toc_apes.html" title="apes">     <contents url="chimps.html" title="some stuff chimps" /> </contents> <contents url="toc_cats" title="cats">     <contents url="hairless_cats.html" title="omg did hair go?"/>     <contents url="wild_cats.html" title="these things frighten me"/> </contents> <contents url="toc_dogs.html" title="dogs">     <contents url="toc_snorty_dogs.html" title="snorty dogs">         <contents url="boston_terriers.html" title="boston terriers" />         <contents url="french_bull_dogs.html" title="frenchies" />     </contents> </contents> </contents> 

here xslt:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="text" indent="no"/>  <!-- variable sets delimiter symbol excel use seperate cells --> <xsl:variable name="delimiter">@</xsl:variable>  <xsl:template match="contents">      <!-- prints url -->     <xsl:value-of select="@url"/>     <xsl:copy-of select="$delimiter" />      <!-- prints title -->     <xsl:apply-templates select="@title"/>     <xsl:copy-of select="$delimiter" />      <!-- prints depth--i.e., number of categories, sub-categories, etc. -->     <xsl:value-of select="count(ancestor::*[@title])"/>     <xsl:copy-of select="$delimiter" />      <!-- sets categories -->      <xsl:for-each select="ancestor::*[@title]">         <xsl:apply-templates select="@title"/>         <xsl:if test="position() != last()">             <xsl:copy-of select="$delimiter" />         </xsl:if>     </xsl:for-each>     <xsl:text>&#xa;</xsl:text> </xsl:template>  <xsl:template match="/">      <!-- creates column headings manually -->     <xsl:text>url</xsl:text>     <xsl:copy-of select="$delimiter" />     <xsl:text>title</xsl:text>     <xsl:copy-of select="$delimiter" />     <xsl:text>depth</xsl:text>     <xsl:copy-of select="$delimiter" />     <xsl:text>level 1</xsl:text>     <xsl:copy-of select="$delimiter" />     <xsl:text>level 2</xsl:text>     <xsl:copy-of select="$delimiter" />     <xsl:text>&#xa;</xsl:text>      <xsl:apply-templates select="//contents"/> </xsl:template>  </xsl:stylesheet> 

the maximum of (ancestor count, in case) selected. sort quality in descending order, store first value variable.

<xsl:variable name="levels">   <xsl:for-each select="//contents[not(*)]">     <xsl:sort select="count(ancestor::*)" data-type="number" order="descending" />     <xsl:if test="position() = 1">       <xsl:value-of select="count(ancestor::*)" />     </xsl:if>   </xsl:for-each> </xsl:variable> 

but not interested in number, interested in headers:

<xsl:for-each select="//contents[not(*)]">   <xsl:sort select="count(ancestor::*)" data-type="number" order="descending" />   <xsl:if test="position() = 1">     <xsl:for-each select="ancestor::*">       <!-- 1 header each ancestor of nested node -->       <xsl:value-of select="concat('level ', position())" />       <xsl:choose>         <xsl:when test="position() = last()">           <xsl:text>&#xa;</xsl:text>         </xsl:when>         <xsl:otherwise>           <xsl:value-of select="$delimiter" />         </xsl:otherwise>       </xsl:choose>     </xsl:for-each>   </xsl:if> </xsl:for-each> 

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

keyboard - C++ GetAsyncKeyState alternative -

android - java.net.UnknownHostException(Unable to resolve host “URL”: No address associated with hostname) -