[xsl] Counting proper elements on a path

Subject: [xsl] Counting proper elements on a path
From: Marcin Miłkowski <milek_pl@xxxxx>
Date: Thu, 04 Aug 2005 12:42:02 +0200
Hi,

I've got a following problem: I'm processing two files with a little different structure (different hierarchy). I need to get a text() snippet from the <source> or <target> element and to put it into a proper place in the <Tuv> element.

<source>
<g ts="x-skl-snip" id="61"/>
With
<g id="d1e113" ts="x-df-contents:Bold=on;"/>
<ph id="d1e114"><STRONG></ph>
<g ts="x-skl-snip" id="63"/>
Motorola mobile PhoneTools Deluxe
<g id="d1e113"/>
<ph id="d1e117"></STRONG></ph>
<g ts="x-skl-snip" id="65"/>
, get the best of your mobile phone and your PC.
<ph id="d1e120"><BR></ph>
<g ts="x-skl-snip" id="67"/>
The Deluxe edition not only provides you with enhanced features compared to the standard edition but also with brand new features.
</source>


The other file has a following structure:

<Tuv Lang="EN-US">%%%61%%%
<df Bold="on">
<ut Type="start" RightEdge="angle" DisplayText="STRONG">&lt;STRONG&gt;</ut>
%%%63%%%</df>
<ut Type="end" LeftEdge="angle" DisplayText="STRONG">&lt;/STRONG&gt;</ut>
%%%65%%%
<ut DisplayText="BR">&lt;BR&gt;</ut>
%%%67%%%
</Tuv>


The text snippets are uniquely numbered with id on the g element (like <g ts="x-skl-snip" id="61"/>). These ids are in the second file as a placeholders for text snippets (like %%%61%%%%) above. What I want to get is a second file with placeholders replaced by proper text snippets. <ut> always corresponds to <ph>, but <df> corresponds to <g/> and </df> to <g/>, where @ts='x-df-contents:...'.

A tried the following template ($translation holds the first file, the current document is the file with placeholders; the default template is simply an identity transformation):

<xsl:template match="//text()">
<xsl:choose>
<xsl:when test="matches(.,'%%%')">
<xsl:variable name="trans_id" select="replace(.,'%%%','')"/>
<xsl:variable name="pos" select="count(preceding-sibling::text())+1"/>
<xsl:value-of select="$translation//g[@id=$trans_id]/parent::*/text()[$pos]"/>
<xsl:if test="not($translation//g[@id=$trans_id][@ts='x-skl-snip'])">
<xsl:message terminate="yes">
Error: The translated file is corrupt. The identifier <xsl:value-of select="$trans_id"/> is missing.
</xsl:message>
</xsl:if>
<xsl:if test="not($translation//g[@id=$trans_id]/parent::*/text()[$pos])">
<xsl:message terminate="no">
Warning: The text snippet no. <xsl:value-of select="$trans_id"/> is empty.
Attempted position: <xsl:value-of select="$pos"/>.
</xsl:message>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>



The hard part is that <df> can hold text snippets and can be inside the <ut> element and <Tuv> element. The contents of <ut>/text() is never a text snippet to be replaced. So the solution must also account for such structures as:


<Tuv Lang="EN-US">
	<ut DisplayText="IMG">
	<IMG src="Logo.gif" align=right>
	</ut>
	<df Italic="on">
		<ut Type="start" RightEdge="angle" DisplayText="CITE">
			<CITE>
		</ut>
		B)2004 Foobar Software.
		<ut DisplayText="BR"><BR></ut>
		All rights reserved.
		<ut DisplayText="BR"><BR></ut>
		Tools is a registered
		<ut DisplayText="BR"><BR></ut>
		trademark of Foobar Software.
	</df>
<ut Type="end" LeftEdge="angle" DisplayText="CITE"></CITE></ut>
</Tuv>

What I need is probably counting some preceding siblings but I'm really stuck.

Any ideas how to count starting from //text() to get a proper index on <source> using the id?

Thanks in advance,
	Marcin

Current Thread