Avatar billede shadowsurfer Nybegynder
28. januar 2004 - 14:49 Der er 26 kommentarer og
1 løsning

kuk i nested for-each.

Jeg har nogle problemer med at lave en nested for-each sætning, hvor første niveau af XML strukturen har formen:
<TEI.2>
<pb id="x" />
  ...
<pb id="z" />
  ...
</TEI.2>

Sætningen virker fint når første niveau har formen:
<TEI.2>
<pb id="x">
  .....
</pb>
<pb id="z">
  .....
</pb>
</TEI.2>

Mit problem er bare jeg skal bruge den øverste form!


----------- XML fil ------------------------
<TEI.2>

<pb id="1r" />
<l id="1" id2="1">1.1 det er en prøve, Ivan Loeveridder</l>
<l id="2" id2="2">1.2 det er en prøve, Ivan Loeveridder</l>
<l id="3" id2="30">1.3 det er en prøve, Ivan Loeveridder</l>
<l id="4" id2="31">1.4 det er en prøve, Ivan Loeveridder</l>
<l id="5" id2="32">1.5 det er en prøve, Ivan Loeveridder</l>
<l id="6" id2="33">1.6 det er en prøve, Ivan Loeveridder</l>


<pb id="1v" />
<l id="7" id2="36">2.1 det er en prøve, Ivan Loeveridder</l>
<l id="8" id2="37">2.2 det er en prøve, Ivan Loeveridder</l>
<l id="9" id2="38">2.3 det er en prøve, Ivan Loeveridder</l>
<l id="10" id2="41">2.4 det er en prøve, Ivan Loeveridder</l>
<l id="11" id2="42">2.5 det er en prøve, Ivan Loeveridder</l>

<pb id="2r" />
<l id="12" id2="43">3.1 det er en prøve, Ivan Loeveridder</l>
<l id="13" id2="44">3.2 det er en prøve, Ivan Loeveridder</l>
<l id="14" id2="45">3.3 det er en prøve, Ivan Loeveridder</l>
<l id="15" id2="46">3.4 det er en prøve, Ivan Loeveridder</l>
<l id="16" id2="47">3.5 det er en prøve, Ivan Loeveridder</l>
<l id="17" id2="48">3.6 det er en prøve, Ivan Loeveridder</l>

</TEI.2>

------------ XSL fil ----------------------

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="iso-8859-1"/>
<xsl:param name="linenumberN" />
<xsl:param name="linenumberB" />
<xsl:param name="pageNumber" />
<xsl:template match="/">
  <table bgcolor="#eeeeee">
  <xsl:for-each select="TEI.2/pb">
    <xsl:if test="@id = $pageNumber or $pageNumber = alle">
      <tr>
      <th bgcolor="#aaaabb">
        Normal:
      </th>
      <th bgcolor="#bbbbaa">
        Brandt:
      </th>
      <th bgcolor="#aaaaaa">
        Side: <xsl:value-of select="@id" />
      </th>
      </tr>
      <xsl:for-each select="l">
      <tr>
        <xsl:choose>
        <xsl:when test="$linenumberN = @id or $linenumberB=@id2">
          <xsl:attribute name="bgcolor">#cacaca</xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="bgcolor">#fefefe</xsl:attribute>
        </xsl:otherwise>
        </xsl:choose>
        <td>
        <xsl:if test="@id mod 5 = 0 or not(@id = (number(preceding::l[1]/@id)+1)) or position() = 1">
          <xsl:value-of select="@id" />
        </xsl:if>
        </td>
        <td>
        <xsl:if test="@id2 mod 5 = 0 or not(@id2 = (number(preceding::l[1]/@id2)+1)) or position() = 1">
          <xsl:value-of select="@id2" />
        </xsl:if>
        </td>
        <td>
        <xsl:value-of select="." />
        </td>
      </tr>
      </xsl:for-each>
    </xsl:if>
  </xsl:for-each>
  </table>
</xsl:template>
</xsl:stylesheet>

---------- output -------------------

<table bgcolor="#eeeeee">
<tr>
  <th bgcolor="#aaaabb">
  Normal:
  </th>
  <th bgcolor="#bbbbaa">
  Brandt:
  </th>
  <th bgcolor="#aaaaaa">
  Side: 2r
  </th>
</tr>
</table>
Avatar billede nute Nybegynder
28. januar 2004 - 16:24 #1
hmm... kan du ikke forklare hvad det er du prøver at opnå ? På mig virker det som om alle <I/> noder tilhører en <pb/> node. Hvis dette er tilfælde, så er det jo forsåvidt nærliggende at gruppere sådan:

<pb>
<I/>
<I/>
</pb>

En anden ting, er at du i din "id" attribut har både tal og bokstaver. Umiddelbart ser det ud til at bokstaven angiver hvor din <pb> skal placeres i output. hvis dette er tilfælde, så vil jeg påstå at du har misforstået noget grundlæggende ved tankegangen i XML. XML er præsentations-uafhængig. hvis du vil præsentere den ene <pb> til højre og den anden til venstre, så er det dit XSL der skal bestemme dette. Fx ved at se om der findes 2 <pb> med id=1 ... hvis der er 2 stykker, så skal den ene placeres til højre og den anden til venstre ... hvis der så er flere, har man også mulighed for at XSL tager sig af dette.

Hvis dette er en forkert betragtning, så vil jeg påpege at dine formater i 'id' attributten er inkonsekvent. Den ene id har mellemrum mellem tal og bokstav og den anden har det ikke.

Men ... prøv at forklar med ord, hvad det er du prøver at gøre .. .så er det nemmere for os at forstå hvad det er du ønsker, og så er det nemmere at hjælpe ;-)

/nute
Avatar billede shadowsurfer Nybegynder
28. januar 2004 - 16:48 #2
XML'en er en beskrivelse af indholdet i en tekst fra den gang runder konge var knægt. "pb" er det tag, der er bestemt til at beskrive hvornår en der er et PageBrack, af en org der hedder Text Encoding Initiative (TEI). Og grunden til der et både bokstaver og tal i side id'en, er at siderne er nummeret efter et system fra den gang.
Grunden til jeg ikke kan bruge <pb>....</pb>, er at der kan være flere udgave af den samme tekst i brug under oversættelsen, dele af siderne kan jo mangle eller være ødelagt.

Teksten er opbygget af vers som, de bliver gruperet ved hjælp en "l" som fortæller hvornår linien starter og slutter. Der er 2 linie tæller, da der er 2 måder at tælle dem på.

Jeg har ikke misforstået hvad xml er, det er en måde at beskrive data på, ikke hvordan de vises, det bruger man XSLT og CSS til.

Det jeg gerne vil er, at lave en tabel, der for hvert side skrive hvilke side det drejersig om, og lige skrive navnene på de 2 vers tæller.
nummeret på de løbende vers tæller skal vises hvis de gå op i 5, ikke er fortløbende for den linie der kom før, eller en den første på en side. linierne skal så vises i det sidste fældt af tabellen.
hele linien skal markers med en anden farve, hvis den er udvalg. denne udvælgelse kan foretages ved hjælp af begge vers tæller.

Normalt vil kun 1 side blive vist, men der skal være mulighed for at vise alle.
Avatar billede shadowsurfer Nybegynder
28. januar 2004 - 16:52 #3
Er der en måde, at stoppe XSLT'en når der er fundet ét match af den ønsket side, sådan så hele xml'en ikke gennemløbes, lige som man med SQL kan lave limit 1.
Avatar billede shadowsurfer Nybegynder
28. januar 2004 - 17:01 #4
Når jeg er helt færdig skal XML'en overholde DTD udarbejdet af TEI, jeg begynde dog først på XSLT i sidste uge, så jeg tager et skridt af gangen... den DTD er VILDT stor!
Avatar billede shadowsurfer Nybegynder
28. januar 2004 - 18:23 #5
JEg har fundet ud af hvordan jeg fanger "l", det skal gøres ved /TEI.2/l istedet for l, det betyder bare at jeg ikke få side skiftende med
Avatar billede nute Nybegynder
29. januar 2004 - 10:09 #6
oki ... så er det måske lidt nemmere at forstå :-) Jeg satte kun spørgsmålstegn med din "XML viden" hvis min betragtning om 'id' attributtet på <pb> tagget var sandt:

"Umiddelbart ser det ud til at bokstaven angiver hvor din <pb> skal placeres i output. hvis dette er tilfælde, så vil jeg påstå at du har misforstået noget grundlæggende ved tankegangen i XML"

Nu har du jo givet en forklaring på hvorfor attributtens værdi ser ud som den gør, og jeg har ingen grund til at "beskylde" dig for noget ;-)

Men ... for at lige prøve at opsummere/klargøre - jeg er stadig ikke *helt* med på din XML.

1) Dit XML format bliver ikke bestemt af dig. XML'en ser sådan ud som den gør, og dette er ikke noget du kan ændre på (dette er helt fair, selv om jeg måske vil være hård nok til at sige at du sidder med et utaknemlig arbejde da jeg mener at XML'en umiddelbart ser "forfærdelig" ud).

2) <pb> tagget bruges til at beskrive et "PageBrack" ??? hvad er et "PageBrack" ? det er ikke pagebreak (sideskift) du mener ?

3) Jeg er hellere ikke helt med på hvorfor du ikke kan bruge <pb>..</pb>. Og jeg er hellere ikke helt med på hvad du mener med "at der kan være flere udgave af den samme tekst i brug under oversættelsen, dele af siderne kan jo mangle eller være ødelagt" ... hvis noget mangler eller er ødelagt, så vil vel ikke dette være med i XML'en ?!

4) Kan du ikke lige poste dit forventede output - altså dét output du forventer fra transformationen. Dette kan måske være til hjælp for forståelsen.

/nute
Avatar billede shadowsurfer Nybegynder
29. januar 2004 - 14:34 #7
2)
Ja, undskyld, det er naturlivis PageBreak.

3)
Hvis der er noget der er ødelagt, kigger man i en anden kilde for at genskabe det ødelagte, der kan derfor være flere steder hvor man skifter til side 2... Det er en uheldig måde at gøre det på, men sådan er det bestemt fra orginisationen TEI, indtilvidere har jeg da også brugt <pb>...</pb>
Så jeg kunne teste! Jeg ville også mene at det er sådan det skal gøres, men TEI har en anden opfattelse. deres standart er fuldt af sprog- og literaturforsker over hele verden.

4)
Naturligvis. der er rette lidt i xml'en og xslt'en i mellem tiden:

---------- XML ---------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="../xslt/Translit.xsl"?>
<TEI.2>

<pb id="1r" />
<l id="1" id2="1">1.1 det er en prøve, Ivan Loeveridder</l>
<l id="2" id2="2"><add place="marginleft" >tilføjelse, venstre</add>1.2 det er en prøve, Ivan Loeveridder</l>
<l id="3" id2="30">1.3 det er en prøve, Ivan Loeveridder</l>
<l id="4" id2="31">1.4 det er en prøve, Ivan Loeveridder</l>
<l id="5" id2="32">1.5 det er en prøve, Ivan Loeveridder</l>
<l id="6" id2="33"><add place="marginright">tilføjelse, højere</add>1.6 det er en prøve, Ivan Loeveridder</l>

<pb id="1v" />
<l id="7" id2="36">2.1 det er en prøve, Ivan Loeveridder</l>
<l id="8" id2="37">2.2 det er en prøve, Ivan Loeveridder</l>
<l id="9" id2="38">2.3 det er en prøve, Ivan Loeveridder</l>
<l id="10" id2="41">2.4 det er en prøve, Ivan Loeveridder</l>
<l id="11" id2="42">2.5 det er en prøve, Ivan Loeveridder</l>

<pb id="2r" />
<l id="12" id2="43"><add place="marginleft" >tilføjelse, venstre</add>3.1 det er en prøve, Ivan Loeveridder</l>
<l id="13" id2="44">3.2 det er en prøve, Ivan Loeveridder</l>
<l id="14" id2="45">3.3 det er en prøve, Ivan Loeveridder</l>
<l id="15" id2="46">3.4 det er en prøve, Ivan Loeveridder</l>
<l id="16" id2="47">3.5 det er en prøve, Ivan Loeveridder</l>
<l id="17" id2="48"><add place="marginright">tilføjelse, højere</add>3.6 det er en prøve, Ivan Loeveridder</l>

<pb id="3r" />
<l id="18" id2="49">4.1 det er en prøve, Ivan Loeveridder</l>
<l id="19" id2="50">4.2 det er en prøve, Ivan Loeveridder</l>
<l id="20" id2="51">4.3 det er en prøve, Ivan Loeveridder</l>
<l id="21" id2="63">4.4 det er en prøve, Ivan Loeveridder</l>
<l id="22" id2="64">4.5 det er en prøve, Ivan Loeveridder</l>
<l id="23" id2="65">4.6 det er en prøve, Ivan Loeveridder</l>
<l id="24" id2="66">4.7 det er en prøve, Ivan Loeveridder</l>
<l id="25" id2="76">4.8 det er en prøve, Ivan Loeveridder</l>

<pb id="3v" />
<l id="26" id2="77">5.1 det er en prøve, Ivan Loeveridder</l>
<l id="27" id2="78">5.2 det er en prøve, Ivan Loeveridder</l>
<l id="28" id2="79">5.3 det er en prøve, Ivan Loeveridder</l>
<l id="29" id2="80">5.4 det er en prøve, Ivan Loeveridder</l>
<l id="30" id2="81">5.5 det er en prøve, Ivan Loeveridder</l>
<l id="31" id2="87">5.6 det er en prøve, Ivan Loeveridder</l>
<l id="32" id2="88">5.7 det er en prøve, Ivan Loeveridder</l>
<l id="33" id2="89">5.8 det er en prøve, Ivan Loeveridder</l>

</TEI.2>

---------- XSLT ---------------------------
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="iso-8859-1"/>
<xsl:param name="linenumberN" />
<xsl:param name="linenumberB" />
<xsl:param name="pageNumber" />
<xsl:param name="showN" />
<xsl:param name="showB" />
<xsl:template match="/">
  <table bgcolor="#eeeeee">
  <xsl:for-each select="TEI.2/pb">
    <xsl:if test="@id = $pageNumber or $pageNumber = alle">
      <tr>
      <xsl:if test="$showN">
        <td bgcolor="#aaaabb">
        Normal:
        </td>
      </xsl:if>
      <xsl:if test="$showB">
        <td bgcolor="#bbbbaa">
        Brandt:
        </td>
      </xsl:if>
      <td>
      </td>
      <td bgcolor="#aaaaaa">
        Side: <xsl:value-of select="@id" />
      </td>
      <td>
      </td>
      </tr>
      <xsl:for-each select="l">
      <tr>
        <xsl:choose>
        <xsl:when test="$linenumberN = @id or $linenumberB=@id2">
          <xsl:attribute name="bgcolor">#cacaca</xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="bgcolor">#fefefe</xsl:attribute>
        </xsl:otherwise>
        </xsl:choose>
        <xsl:if test="$showN">
        <td>
          <xsl:if test="@id mod 5 = 0 or not(@id = (number(preceding::l[1]/@id)+1)) or position() = 1">
          <xsl:value-of select="@id" />
          </xsl:if>
        </td>
        </xsl:if>
        <xsl:if test="$showB">
        <td>
        <xsl:if test="@id2 mod 5 = 0 or not(@id2 = (number(preceding::l[1]/@id2)+1)) or position() = 1">
          <xsl:value-of select="@id2" />
          </xsl:if>
        </td>
        </xsl:if>
        <td>
        <xsl:for-each select="add">
          <xsl:if test="@place = 'marginleft'">
          <xsl:value-of select="." />
          </xsl:if>
        </xsl:for-each>
        </td>
        <td>
        <xsl:value-of select="text()" />
        </td>
        <td>
        <xsl:for-each select="add">
          <xsl:if test="@place = 'marginright'">
          <xsl:value-of select="." />
          </xsl:if>
        </xsl:for-each>
        </td>
      </tr>
      </xsl:for-each>
    </xsl:if>
  </xsl:for-each>
  </table>
</xsl:template>
</xsl:stylesheet>
------- Forvendte output med parameterne, pageNumber = 2r, showN = true, showB = true ----
table bgcolor="#eeeeee"><tr><td bgcolor="#aaaabb">
        Normal:
        </td><td bgcolor="#bbbbaa">
        Brandt:
        </td><td/><td bgcolor="#aaaaaa">
        Side: 2r</td><td/></tr><tr bgcolor="#fefefe"><td>12</td><td>43</td><td>tilføjelse, venstre</td><td>3.1 det er en prøve, Ivan Loeveridder</td><td/></tr><tr bgcolor="#fefefe"><td/><td/><td/><td>3.2 det er en prøve, Ivan Loeveridder</td><td/></tr><tr bgcolor="#fefefe"><td/><td>45</td><td/><td>3.3 det er en prøve, Ivan Loeveridder</td><td/></tr><tr bgcolor="#fefefe"><td>15</td><td/><td/><td>3.4 det er en prøve, Ivan Loeveridder</td><td/></tr><tr bgcolor="#fefefe"><td/><td/><td/><td>3.5 det er en prøve, Ivan Loeveridder</td><td/></tr><tr bgcolor="#fefefe"><td/><td/><td/><td>3.6 det er en prøve, Ivan Loeveridder</td><td>tilføjelse, højere</td></tr></table>

-----------------------
Jeg har lavet det forvendte output ved at lave <pd>....</pb>, istedet for <pb />
Avatar billede nute Nybegynder
31. januar 2004 - 17:08 #8
undskyld jeg ikke har vendt tilbage før nu, men jeg har været optaget :-|

anyway .. her er et lille bud på hvad du kan gøre. jeg ved det ikke er dig der har lavet DTD'en, men jeg må godt nok indrømme at den er mindre pæn !! Det er svært at lave ordentlig XSL på en grim XML.

kig på dette, og se om dette ikke er noget ála det du forventer:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="iso-8859-1"/>
    <xsl:param name="linenumberN"/>
    <xsl:param name="linenumberB"/>
    <xsl:param name="pageNumber">2r</xsl:param>
    <xsl:param name="showN">true</xsl:param>
    <xsl:param name="showB">true</xsl:param>
    <xsl:template match="/">
        <table bgcolor="#eeeeee">
            <xsl:call-template name="buildTableHeader"/>
            <xsl:apply-templates/>
        </table>
    </xsl:template>
    <xsl:template match="TEI.2">
        <xsl:call-template name="buildTable"/>
    </xsl:template>
    <xsl:template name="buildTable">
        <xsl:call-template name="buildRow">
            <xsl:with-param name="pNode" select="/TEI.2/pb[ @id = '2r' ]/following::*[1]">
            </xsl:with-param>
        </xsl:call-template>
    </xsl:template>
    <xsl:template match="pb|I"/>
    <xsl:template name="buildTableHeader">
        <tr>
            <xsl:if test="$showN">
                <td bgcolor="#aaaabb">Normal:</td>
            </xsl:if>
            <xsl:if test="$showB">
                <td bgcolor="#bbbbaa">Brandt:</td>
            </xsl:if>
            <td/>
            <td bgcolor="#aaaaaa">Side: <xsl:value-of select="$pageNumber"/>
            </td>
            <td/>
        </tr>
    </xsl:template>
    <xsl:template name="buildRow">
        <xsl:param name="pNode"/>
        <tr bgcolor="#fefefe">
            <td>
                <xsl:value-of select="$pNode/@id"/>
            </td>
            <td>
                <xsl:value-of select="$pNode/@id2"/>
            </td>
            <td>
                <xsl:value-of select="$pNode/add[ @place = 'marginleft' ]"/>

            </td>
            <td>
                <xsl:value-of select="$pNode/text()"/>
               
            </td>
            <td>
                <xsl:value-of select="$pNode/add[ @place = 'marginright' ]"/>
            </td>
        </tr>
        <xsl:if test="local-name( /TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1] ) = 'l'">
            <xsl:call-template name="buildRow">
                <xsl:with-param name="pNode" select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

/nute
Avatar billede nute Nybegynder
31. januar 2004 - 17:09 #9
ups ... jeg har vidst ikke taget høje for udskrivningen af tællerne på dine vers ... de kommer om lidt
Avatar billede nute Nybegynder
31. januar 2004 - 18:49 #10
skift ud:

<xsl:template name="buildRow">
...
</xsl:template>

med denne:

    <xsl:template name="buildRow">
        <xsl:param name="pNode"/>
        <xsl:param name="pCounter"/>
        <xsl:variable name="id"><xsl:value-of select="$pNode/@id"/></xsl:variable>
        <xsl:variable name="id2"><xsl:value-of select="$pNode/@id2"/></xsl:variable>
        <xsl:variable name="nodeText"><xsl:value-of select="$pNode/text()"/></xsl:variable>
        <xsl:variable name="addLeft"><xsl:value-of select="$pNode/add[ @place = 'marginleft' ]"/></xsl:variable>
        <xsl:variable name="addRight"><xsl:value-of select="$pNode/add[ @place = 'marginright' ]"/></xsl:variable>
        <xsl:variable name="precedingNodeID"><xsl:value-of select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/preceding::l[1]/@id"/></xsl:variable>
        <xsl:variable name="precedingNodeID2"><xsl:value-of select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/preceding::l[1]/@id2"/></xsl:variable>
        <tr bgcolor="#fefefe">
            <td>
                <xsl:if test="$id mod 5 = 0 or not( ( $id - 1 ) = $precedingNodeID ) or $pCounter = 1">
                    <xsl:value-of select="$id"/>
                </xsl:if>
            </td>
            <td>
                <xsl:if test="$id2 mod 5 = 0 or not( ( $id2 - 1 ) = $precedingNodeID2 ) or $pCounter = '1'">
                    <xsl:value-of select="$id2"/>
                </xsl:if>
            </td>
            <td>
                <xsl:value-of select="$addLeft"/>
            </td>
            <td>
                <xsl:value-of select="$nodeText"/>
               
            </td>
            <td>
                <xsl:value-of select="$addRight"/>
            </td>
        </tr>
        <xsl:if test="local-name( /TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1] ) = 'l'">
            <xsl:call-template name="buildRow">
                <xsl:with-param name="pNode" select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1]"/>
                <xsl:with-param name="pCounter"><xsl:value-of select="number( $pCounter ) + 1" /></xsl:with-param>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

/nute
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 10:24 #11
Undskyld jeg ikke vender tilbage før nu. Men jeg har været væk fra en computer siden fredag morgen.
--

Efter at havde rette:
<xsl:with-param name="pNode" select="/TEI.2/pb[ @id = '2r' ]/following::*[1]">
Til
<xsl:with-param name="pNode" select="/TEI.2/pb[ @id = $pageNumber ]/following::*[1]">

Virker det ;-)
Nu kommer så det punkt hvor jeg prøver at forstå hvad der sker, og finder ud af, at lidt over en uges erfaring med xslt, ikke er nok til at forstå det.

Du kan få de 90 point for dit svar, men hele 200 hvis du kan forklare mig hvad der sker! Jeg vil vildt gerne lære noget af det her ;-)
Mit største problem er at forstå hvad der sker i [..]
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 10:29 #12
Kan du anbefalde et godt website der forklarer om XSLT eller en god bog?
Avatar billede nute Nybegynder
04. februar 2004 - 10:33 #13
ahh .. ja, jeg kan godt se at der var en lille "bug" der kom med i min posting ... jeg skal prøve at forklare hvad der sker.

i mellemtiden kan du jo kigge på http://www.w3schools.org ... der har de en god tutorial om XSLT

ellers kan du kigge på http://www.topxml.com

jeg vender tilbage om lidt med en forklaring :-)
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 11:01 #14
w3schools.org er jeg har lært hvad jeg kan ;-)
Avatar billede nute Nybegynder
04. februar 2004 - 11:05 #15
Det første der sker:

<xsl:template match="/">

er at finde roden af din XML (så meget har du vel regnet ud, men jeg tager det hele ... jeg ved jo ikke helt hvor du falder af ;o] ) Det eneste der laves når roden bliver fundet, er at der laves en tabel. Inde i denne template, så kalder jeg en anden template:

<xsl:call-template name="buildTableHeader"/>

for at skrive ud dine tabeloverskrifter .. .jeg kunne sagtens bare have skrevet disse ud i den samme template, men jeg kan godt lide at bryde "logiske" dele op i biter.

Derefter kaldes

<xsl:apply-templates />

dette er en instruktion om at alle subnoder under roden skal findes og behandles. jeg har laves 2 templates der behandler subnoder:

<xsl:template match="pb|I"/>
og
<xsl:template match="TEI.2">

den første template laver intet, og er en instruktion om at når der lokaliseres en <pb/> eller ('eller' operatoren i XSLT er et 'pipe' tegn: |) <I/> node, så skal der ikke ske noget.

Så kommer det "sjove" :-) Inde i templaten, der matcher TEI.2, kalder jeg en anden template der starter med at lave rækker i din tabel, og det er i denne template (buildRow) hele fidusen ligger. denne template er en rekursiv template, noget der er meget normalt at gøre brug af i XSLT. Siden XSLT processeres "forward only", så har man ingen muligheder som man har i fx scriptsprog - at gemme værdier i globale variabler, springe frem og tilbage i koden osv.

I kaldet til 'buildRow' sender jeg så med den første efterfølgende node til den node du beder om at få vist. Grunden til at jeg sender hele noden med til min template, er at så har jeg et udgangspunkt for videre søgning i XML'en. I min 'buildRow' template hiver jeg så de forskellige attributter jeg har behov for, ind i variabler. Derefter skriver jeg så ud alle rækker.

Så kommer tricket: helt til sidst i 'buildRow', laver jeg en 'if' statement:
<xsl:if test="local-name( /TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1] ) = 'l'">

denne tjekker navnet på den node der ligger *efter* den  node jeg lige har skrevet ud ... hvis noden hedder <I/>, så kalder jeg 'buildRow' templaten en gang til for at skrive ud denne række, ellers lader jeg det være, og vupti, så er hele tabellen skrevet ud.

Det er ikke nogen heksekunst med XSL ... man skal bare lære sig at tænke på en lidt anden måde end med scriptsprog :-)

håber dette var til hjælp

/nute
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 12:26 #16
Mange tak for gennemgangen, jeg kan nu næsten forstå det hele, det enste jeg mangler er, hvad det betyder, når noget stå i [].
Avatar billede nute Nybegynder
04. februar 2004 - 12:37 #17
fx denne her:

/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1]

kan deles op i 2 dele ... den første del (/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]) betyder:

giv mig den /TEI.2/I node der har "id" lig med $pNode/@id ($ refererer til en variabel eller parameter) og har "id2" lig med $pNode/id2. [] i denne sammenheng bruges for at sætte kriterier på "forespørgselen"

Den anden del (/following-sibling::*[1]) betyder:

fra den node som blev fundet i første del (lige ovenfor), skal jeg have det første "søsken". following-sibling giver de noder der ligger efter den node du står på - på samme niveau - og vil i dette tilfælde give alle de noder der ligger på samme niveau *efter* den node du  står på. du er kun interesseret i den første noden, noget du angiver med [1]. på samme måde som at angive position i en array i fx. javascript

/nute

når jeg har
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 13:27 #18
Jeg tror jeg har fattede det nu ;-) Mange tak.

Der er rettede lidt i koden, så man også kan markere en valgt linie, koden ser nu således ud:

-------------------------
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="iso-8859-1"/>
    <xsl:param name="linenumberN"/>
    <xsl:param name="linenumberB"/>
    <xsl:param name="pageNumber" />
    <xsl:param name="showN" />
    <xsl:param name="showB" />
    <xsl:template match="/">
        <table bgcolor="#eeeeee">
            <xsl:call-template name="buildTableHeader"/>
            <xsl:apply-templates/>
        </table>
    </xsl:template>
    <xsl:template match="TEI.2">
        <xsl:call-template name="buildTable"/>
    </xsl:template>
    <xsl:template name="buildTable">
        <xsl:call-template name="buildRow">
            <xsl:with-param name="pNode" select="/TEI.2/pb[ @id = $pageNumber ]/following::*[1]">
            </xsl:with-param>
        </xsl:call-template>
    </xsl:template>
    <xsl:template match="pb|I"/>
    <xsl:template name="buildTableHeader">
        <tr>
            <xsl:if test="$showN">
                <td bgcolor="#aaaabb">Normal:</td>
            </xsl:if>
            <xsl:if test="$showB">
                <td bgcolor="#bbbbaa">Brandt:</td>
            </xsl:if>
            <td/>
            <td bgcolor="#aaaaaa">Side: <xsl:value-of select="$pageNumber"/>
            </td>
            <td/>
        </tr>
    </xsl:template>
  <xsl:template name="buildRow">
        <xsl:param name="pNode"/>
        <xsl:param name="pCounter"/>

        <xsl:variable name="id">
        <xsl:value-of select="$pNode/@id"/>
        </xsl:variable>

        <xsl:variable name="id2">
        <xsl:value-of select="$pNode/@id2"/>
        </xsl:variable>

        <xsl:variable name="nodeText">
        <xsl:value-of select="$pNode/text()"/>
        </xsl:variable>

        <xsl:variable name="addLeft">
        <xsl:value-of select="$pNode/add[ @place = 'marginleft' ]"/>
        </xsl:variable>

        <xsl:variable name="addRight">
        <xsl:value-of select="$pNode/add[ @place = 'marginright' ]"/>
        </xsl:variable>

        <xsl:variable name="precedingNodeID">
        <xsl:value-of select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/preceding::l[1]/@id"/>
        </xsl:variable>

        <xsl:variable name="precedingNodeID2">
        <xsl:value-of select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/preceding::l[1]/@id2"/>
        </xsl:variable>

        <tr>
        <xsl:choose>
          <xsl:when test="$id = $linenumberN or $id2 = $linenumberB">
          <xsl:attribute name="bgcolor">#dedede</xsl:attribute>
          </xsl:when>
          <xsl:otherwise>
          <xsl:attribute name="bgcolor">#fbfbfb</xsl:attribute>
          </xsl:otherwise>
        </xsl:choose>

          <xsl:if test="$showN">
            <td>
                <xsl:if test="$id mod 5 = 0 or not( ( $id - 1 ) = $precedingNodeID ) or $pCounter = 1">
                    <xsl:value-of select="$id"/>
                </xsl:if>
            </td>
          </xsl:if>
          <xsl:if test="$showB">
            <td>
                <xsl:if test="$id2 mod 5 = 0 or not( ( $id2 - 1 ) = $precedingNodeID2 ) or $pCounter = '1'">
                    <xsl:value-of select="$id2"/>
                </xsl:if>
            </td>
        </xsl:if>
            <td>
                <xsl:value-of select="$addLeft"/>
            </td>
            <td>
                <xsl:value-of select="$nodeText"/>
            </td>
            <td>
                <xsl:value-of select="$addRight"/>
            </td>
        </tr>
        <xsl:if test="local-name( /TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1] ) = 'l'">
            <xsl:call-template name="buildRow">
                <xsl:with-param name="pNode" select="/TEI.2/l[ @id = $pNode/@id and @id2 = $pNode/@id2 ]/following-sibling::*[1]"/>
                <xsl:with-param name="pCounter">
                <xsl:value-of select="number( $pCounter ) + 1" />
                </xsl:with-param>

            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
Avatar billede nute Nybegynder
04. februar 2004 - 13:31 #19
det lyder godt - glad for at høre jeg har været til hjælp :-) håber du får meget nytte af XSL ... det er meget sjov når man kommer ind i det

;o]
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 13:57 #20
Skriv et svar, så få du point!
Avatar billede nute Nybegynder
04. februar 2004 - 14:01 #21
et svar, så får du point!

:o]
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 14:01 #22
Kan man finde ud af hvilken siden en givet linie befinder sig på? fx at linie id=10 befinder sig på side 1v?
Avatar billede nute Nybegynder
04. februar 2004 - 14:17 #23
hmm ... den info har du jo i variabelen 'pageNumber'

/nute
'
Avatar billede shadowsurfer Nybegynder
04. februar 2004 - 14:26 #24
Jeg mener, hvis der ikke er angivet noget pageNumber, men kun en linie, kan man så finde ud af hvilken side, den pågældende linie befinder sig på?
Avatar billede nute Nybegynder
04. februar 2004 - 15:26 #25
læg denne ind i din 'buildRow' template, så har du siden til linjen:

<xsl:variable name="pageOfLine"><xsl:value-of select="$pNode/preceding-sibling::pb[ 1 ]/@id" /></xsl:variable>

/nute
Avatar billede shadowsurfer Nybegynder
09. februar 2004 - 09:11 #26
Undskyld det igen tog så lang tid, men endnu en gang, har jeg været uden adgang til en computer med internetopkobling i et stykke tid.


MANGE TAK FOR HJÆLPEN

/The Shadow Surfer
Avatar billede nute Nybegynder
09. februar 2004 - 09:25 #27
selv tak :o]

/nute
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester