[xsl] I only want to process the first node... ;)

Subject: [xsl] I only want to process the first node... ;)
From: Norman Rosner <jeckyll@xxxxxxx>
Date: Tue, 18 Sep 2007 18:13:33 +0200
Hi there!

I have an XML File that looks like this:


<Analysis>

.....
<S>
      <PPER id="s33_5" word="er" lemma="er" morph="3.Nom.Sg.Masc"
trans="he"/>
      <VVFIN id="s33_4" word="verlange" lemma="verlangen"
morph="3.Sg.Pres.Subj"
             trans="request"/>
      <NP>
         <PP>
	           <APPR id="s33_6" word="vor" lemma="vor" morph="--"
trans="over"/>
	           <PIS id="s33_7" word="allem" lemma="alle"
morph="Dat.Sg.Masc" trans="all"/>
         </PP>
         <CNP>
	           <NN id="s33_8" word="Arbeitsmoral" lemma="Arbeitsmoral"
morph="Acc.Sg.Fem"
                trans="employee moral"/>
	           <KON id="s33_9" word="und" lemma="und" morph="--"
trans="and"/>
	           <NP>
	              <ADJA id="s33_10" word="ordentliches"
lemma="ordentlich" morph="Pos.Acc.Sg.Neut"
                     trans="proper"/>
	              <NN id="s33_11" word="Auftreten" lemma="auftreten"
morph="Acc.Sg.Neut"
                   trans="appearence"/>
	           </NP>
         </CNP>
      </NP>
      <PP>
         <APPR id="s33_1" word="Von" lemma="von" morph="--"
trans="of | from"/>
         <PPOSAT id="s33_2" word="seinen" lemma="sein"
morph="Dat.Pl.*" trans="her"/>
         <NN id="s33_3" word="Beschdftigten" lemma="beschdftigter"
morph="Dat.Pl.*"
             trans="employees"/>
      </PP>
  </S>
  <DL>
      <CS>
         <S>
	           <NE id="s34_1" word="Perot" lemma="Perot"
morph="Nom.Sg.Masc" trans="Perot"/>
	           <VAFIN id="s34_2" word="sei" lemma="sein"
morph="3.Sg.Pres.Subj" trans="would be"/>
	           <NP>
	              <ART id="s34_3" word="ein" lemma="ein"
morph="Nom.Sg.Masc" trans="an"/>
	              <ADJA id="s34_4" word="autoritdrer"
lemma="autoritdr" morph="Pos.Nom.Sg.Masc"
                     trans="authoritarian"/>
	              <NN id="s34_5" word="Macher" lemma="Macher"
morph="Nom.Sg.Masc" trans="wright"/>
	           </NP>
         </S>
         <KON id="s34_7" word="und" lemma="und" morph="--"
trans="and"/>
         <S>
	           <NP>
	              <PPOSAT id="s34_11" word="seine" lemma="sein"
morph="Nom.Sg.Fem" trans="her"/>
	              <NN id="s34_12" word="Schwdche" lemma="Schwdche"
morph="Nom.Sg.Fem"
                   trans="weakness"/>
	           </NP>
	           <VAFIN id="s34_9" word="sei" lemma="sein"
morph="3.Sg.Pres.Subj" trans="would be"/>
	           <ADV id="s34_10" word="auch" lemma="auch" morph="--"
trans="too"/>
         </S>
      </CS>
      <S>
         <NP>
	           <ART id="s34_16" word="ein" lemma="ein"
morph="Nom.Sg.Masc" trans="a"/>
	           <NN id="s34_17" word="Manager" lemma="Manager"
morph="Nom.Sg.Masc" trans="manager"/>
         </NP>
         <VVFIN id="s34_14" word="beschreibt" lemma="beschreiben"
morph="3.Sg.Pres.Ind"
                trans="describes"/>
         <PPER id="s34_15" word="ihn" lemma="ihn"
morph="3.Acc.Sg.Masc" trans="him"/>
      </S>
  </DL>
</Analysis>

So there's an Analysis node and several S nodes as siblings. But there are also CS and DL nodes as siblings of the Analysis node. What i want is: Capitalize the first character of every @trans that occurs first in a S node and just print the rest @trans as strings to sdtout ;)

So thats what i wrote:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/
Transform"
		xmlns:xlink="http://www.w3.org/1999/xlink";
		xmlns:mt="machine_translation"
		xmlns:xml="http://www.w3.org/XML/1998/namespace";>

  <xsl:output method="text" omit-xml-declaration="yes"
standalone="yes" indent="no"/>

<xsl:strip-space elements="*"/>


<!-- Capitalize the first character of a given word --> <xsl:function name="mt:capitalize_first"> <xsl:param name="word"/> <xsl:variable name="converted_first_char" select="translate (substring($word,1,1),'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> <xsl:value-of select="concat($converted_first_char, substring ($word, 2, string-length($word)))"/> </xsl:function>

<xsl:template match="S">

    <xsl:variable name="terminals" select="descendant::*[count
(child::*) = 0]"/>

<xsl:value-of select="mt:capitalize_first($terminals[1]/@trans)"/>

    <xsl:for-each select="$terminals[position() != 1]/@trans">
      <xsl:text> </xsl:text>
      <xsl:value-of select="."/>
    </xsl:for-each>

<xsl:text>&#xa;</xsl:text>


</xsl:template> </xsl:stylesheet>

But then i recognized that some S nodes can occur in a CS or DL nodes, so i changed my XPath expression (descendant::*[count (child::*) = 0]) to tis one: ((ancestor::*)[2])/descendant::*[count (child::*) = 0] just to test if it works when i take the ancestor node that comes directly after the Analysis node. It works fine but the fact is that i get the strings printed 2 or three times. In the example above it is:

Perot would be an authoritarian wright and her weakness would be
too a manager describes him
Perot would be an authoritarian wright and her weakness would be
too a manager describes him
Perot would be an authoritarian wright and her weakness would be
too a manager describes him


So i know why it is printed or processed three times: There a three S
nodes inside the DL node. And here's the point: If i processed the
first S node inside a DL or CS node i don't want to process the
following S nodes in that CS or DL node.

I hope that somebody of you can help me and that somebody of you
understand the problem :)

Thanks in advance

norman

Current Thread