lauhub
lauhub

Reputation: 920

How to get the level of a parent node with an attribute that matches a string?

I have this XML file (it is a Freeplane MindMap I want to transform to markdown):

            <node TEXT="About exceptions" LOCALIZED_STYLE_REF="AutomaticLayout.level,2" ID="ID_1944432951" CREATED="1515603952224" MODIFIED="1515603952225">
                <node TEXT="- runtime exceptions (*runtime exceptions*) and its subclasses `:" ID="ID_1822312851" CREATED="1515603952233" MODIFIED="1515603952233">
                    <node TEXT="  - ArrayIndexOutofBounds" ID="ID_1897172344" CREATED="1515603952233" MODIFIED="1515603952233"/>

...

            <node TEXT="Collections" LOCALIZED_STYLE_REF="AutomaticLayout.level,2" ID="ID_1932847832" CREATED="1515603952454" MODIFIED="1515603952460">
                <node TEXT="Classes" LOCALIZED_STYLE_REF="AutomaticLayout.level,3" ID="ID_1207794388" CREATED="1515603952464" MODIFIED="1515603952464">
                    <node TEXT="`Map` is specific..." ID="ID_817824121" CREATED="1515603952464" MODIFIED="1515603952464"/>

I need to add indentation to my output according to how many ancestors there are between the current node and its ancestor (a header node) selected by an attribute.

The header node (or depth reference node)

The matching ancestor's attribute is LOCALIZED_STYLE_REF and it must start with AutomaticLayout.level, (followed by any number: AutomaticLayout.level,1 e.g.)

So I need to add tab characters according to the difference between something like:

I tried the code below but with no success (I don't know how to get the lastHeaderLevel value) :

<xsl:call-template name="addIndentation">
    <xsl:with-param name="currentNodeLevel" select="count(ancestor::*)" />
</xsl:call-template>

<!-- Template to calculate difference between current node's depth and last header's depth  -->
<xsl:template name="calculateIndentation">
    <xsl:param name="currentNodeLevel">0</xsl:param>
    <xsl:call-template name="numberSign">
        <xsl:with-param name="howMany" select="$currentNodeLevel - $lastHeaderLevel - 1"/>
    </xsl:call-template>
</xsl:template>

<!-- Template to change text indentation according to level from last header  -->
<xsl:template name="appendIndentationToOutput">
    <xsl:param name="howMany">0</xsl:param>
    <xsl:if test="$howMany &gt; 0">
        <!-- Add 1 number signs (tab) to output. -->
        <xsl:text>&#x9;</xsl:text>
        <!-- Print remaining ($howMany - 1) number signs. -->
        <xsl:call-template name="addIndentationToOutput">
            <xsl:with-param name="howMany" select="$howMany - 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

The depth between nodes can vary from 0 to n

How can I get the correct depth between a header node and the current node using XSLT v1.0 ?

Upvotes: 0

Views: 126

Answers (1)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25054

The most recent header will be

ancestor::*
  [starts-with(@LOCALIZED_STYLE_REF, 'AutomaticLayout.level,')]
  [1]

I'd define a variable $current-header with that value, and then the difference of depth becomes, as you expect, a matter of

count(ancestor::*) - count($current-header/ancestor::*)

Upvotes: 1

Related Questions