Toon posts:

[XSL/XML] Bepalen van de plaats in een xml file

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

Ik heb een probleempje..

Ik heb een xml file-tje die er ongeveer als volgt uit ziet

<xml>
  <appl/>
  <group> <!-- path="/xml/group[0]/" -->
    <members>
      <appl/>
      <group> <!-- path="/xml/group[0]/members/group[0]/" -->
        <members>
          <appl/>
          <appl/>
        </members>
      </group>
      <appl/>
    </members>
  </group>
  <appl/>
  <group> <!-- path="/xml/group[1]/" -->
    <members>
      <appl/>
      <appl/>
    </members>
  </group>
  <appl/>
</xml>


[PROBLEEM 1] het eerste probleem is het path [/PROBLEEM 1]
via een template match beland ik in de eerste group, het path is zoals aangegeven..
dit path is makkelijk te achterhalen.. maar het word moeilijker om dit te acherhalen
als je je bevind in een group in een group in een group in een group..
dit zou je recursief willen oplossen, maar voor zover ik weet heeft xsl alleen de
beschikking over if en when element keuze mogelijkheden...

[VRAAG] heeft iemand een idee hoe ik dit kan oplossen ?? [/VRAAG]

met if statements lijkt me erg omslachtig..


[PROBLEEM 2] het bepalen van de nummers van de group [/PROBLEEM 2]
het volgende probleem is het volgende.. het nummer van de group moet bepaalt worden
dit is ook een lastig, maar volgens mij een makkelijker probleem.. als ik gebruik
maak van de postion() functie dan telt hij en appl en group.. kan ik dit beperken tot
alleen het bijhouden van het group nummer ?

of is dit het beste op te lossen door zelf een integer bij te houden en deze telkens ophogen
probleem daarbij is wel dat als ik een group in ga in een group ik dat dan opnieuw
moet gaan tellen

[VRAAG] heeft iemand hier een goede oplossing voor ?? [/VRAAG]

Bijvoorbaad dank en met vriendelijke groet,

Ik

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
dit zou je recursief willen oplossen, maar voor zover ik weet heeft xsl alleen de beschikking over if en when element keuze mogelijkheden...
XSLT is juist een en al recusieviteit. Het is gebaseerd op structural recursion. Je gebruikt deze recursie door steeds opnieuw templates toe te passen.

Klein voorbeeldje:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<root>
  <category name="nieuws">
    <category name="java">
    <link name="javalobby" url="http://www.javalobby.org"/>
    <link name="jsurfer" url="http://www.jsurfer.org"/>
    <link name="IBM/Java" url="http://www.java.ibm.com"/>
    <link name="Sun/Java" url="http://java.sun.com"/>
    <link name="javaworld" url="http://www.javaworld.com"/>
    </category>

    <category name=".net">
    <link name="Mono"   url="http://www.go-mono.org"/>
    </category>
  </category>

  <category name="XT">
    <link name="Stratego Language"  url="http://www.stratego-language.org"/>
    <link name="Program Transformation" url="http://www.program-transformation.org"/>
    <link name="ATerm Library"      url="http://www.cwi.nl/projects/MetaEnv/aterm/"/>
  </category>
</root>

en een stylesheet die dit recursief omzet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns="http://www.w3.org/1999/xhtml"
         xmlns:html="http://www.w3.org/1999/xhtml"
     exclude-result-prefixes="xsl html">

  <xsl:output method="xml" indent="yes" encoding="UTF-8"
      doctype-public="-//W3C//DTD XHTML 1.1//EN"
      doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>

  <xsl:template match="root">
    <html>
    <head>
      <title>Bookmarks of Martin Bravenboer</title>
    </head>

    <body>
      <h1>My bookmarks</h1>

      <ul>
        <xsl:apply-templates/>
      </ul>
    </body>
    </html>
  </xsl:template>

  <xsl:template match="link">
    <li>
    <a href="{@url}" alt="{@name}">
      <xsl:value-of select="@name"/>
    </a>
    </li>
  </xsl:template>

  <xsl:template match="category">
    <li>
    <p>
      <xsl:value-of select="@name"/>:
      <ul>
         <xsl:apply-templates/>
      </ul>
    </p>
    </li>
  </xsl:template>

</xsl:stylesheet>
het bepalen van de nummers van de group
Je kan hiervoor een van de axes gebruiken. Het hangt er even vanaf wat je precies wilt welke axes je nodig hebt (waarschijnlijk preceding-sibling).
of is dit het beste op te lossen door zelf een integer bij te houden en deze telkens ophogen.
Dat is imperatief denken: je kan niet zomaar een integer bijhouden en deze ophogen. Je moet denken in XSLT ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Hier nog even een voorbeeld waar je veel aan hebt. Ik heb de template voor 'link' even aangepast om er nummers voor te zetten (tamelijk zinloos omdat XHTML dit zelf natuurlijk ook kan doen ;) ).
code:
1
2
3
4
5
6
7
8
9
  <xsl:template match="link">
    <li>
    <xsl:value-of select="count( preceding-sibling::link )"/>
    <xsl:text>. </xsl:text>
    <a href="{@url}" alt="{@name}">
      <xsl:value-of select="@name"/>
    </a>
    </li>
  </xsl:template>

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Dank u, dank u dank u :P
XSLT is juist een en al recusieviteit. Het is gebaseerd op structural recursion. Je gebruikt deze recursie door steeds opnieuw templates toe te passen.
I Know..

maar wat ik mis is bijvoorbeeld while loops..
om het volgende voor elkaar te krijgen..
code:
1
2
3
4
5
While (element <> root_element)
{
   onthoud_de_naam_van_de_current_node
   element = parent_element
}

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
P3nGu1N: Dank u, dank u dank u :P
Alstu, alstu, alstu :+ .
onthoud
"Onthouden" is imperatief: variabelen die je kan aanpassen. XSLT is een declaratieve taal, waarin er geen 'state' is: variabelen zijn immutable.

Wat je dus moet doen is proberen om een oplossing te vinden in de gedachte van XSLT. Hierbij kunnen de axes vaak behulpzaam zijn, maar je zult zeker ontdekken dat je vaak behoorlijk moet rommelen en knutselen omdat XSLT op dit moment nog niet bepaald uitblinkt qua uitdrukkingskracht.

Zie daarvoor bijvoorbeeld ook dit topic:

[topic=546762/1/400]

Ik laat hier een alternatieve, veel krachtiger oplossing zien in Stratego, een andere transformatie taal. Ook dit zou je goed op kunnen lossen met Stratego, zonder gebruik van axes (die Stratego niet kent).

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
ik heb bijna een oplossing voor mijn path probleem..

Ik roep zo mijn methode aan:
code:
1
    <xsl:call-template name="GetParentName"/>

en de methode ziet er zo uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
    <xsl:template name="GetParentName">
    <xsl:text>/</xsl:text>
        <xsl:choose>
            <xsl:when test="local-name(.) = 'ModReport'">
                <xsl:value-of select="local-name(..)"/>
                <xsl:text>/</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="GetParentName"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:value-of select="local-name(.)"/>
    </xsl:template>

dit zou eigenlijk moeten werken...

maar dit resulteerd in een buffer-overflow in de xsl processor

zit er een fout in of is dit gewoon niet mogelijk op deze manier?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Hum.... eerlijk gezegd vind ik die code er vrij onaantrekkelijk uit zien....

Ik heb ooit een voorbeeld met de ancestor axis gegeven, maar kan helaas het topic niet vinden.... Hier de code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  <xsl:template match="folder|file">
    <tr>
    <xsl:apply-templates select="ancestor::folder" mode="dirty-jump"/>

    <td>
      <xsl:value-of select="@name"/>
    </td>
    </tr>

    <xsl:apply-templates select="folder|file"/>
  </xsl:template>

  <xsl:template match="folder|node" mode="dirty-jump">
    <td>-</td>    
  </xsl:template>

Ik denk dat je ook hier weer gewoon goed moet kijken wat voor mogelijkheden de axes bieden en in dit geval dus de ancestor waarschijnlijk. Ik zou zoveel mogelijk deze vage constructies met named templates proberen te voorkomen.

Ik begrijp trouwens het doel niet helemaal: wil je deze path expressies opnemen in het resultaat van je transformatie? Eventueel kan ik daar nog wel even een voorbeeld van geven als dit inderdaad is wat je bedoeld...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik heb nog maar ff een voorbeeld gemaakt...

Stel ik heb deze xml:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
<folder name="home">
  <folder name="martin">
    <folder name="development">
    <folder name="javahova">
      <file name="tutorial.xml"/> 
      <file name="tutorial.xsl"/> 
    </folder>
    </folder>
    <folder name="uu">
    <file name="presentation.tex"/>
    </folder>
  </folder>
</folder>

en deze stylesheet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0"?>

<xsl:transform version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns="http://www.w3.org/1999/xhtml"
            xmlns:html="http://www.w3.org/1999/xhtml">

  <xsl:output method="xml" indent="yes" encoding="UTF-8"
      doctype-public="-//W3C//DTD XHTML 1.1//EN"
      doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>

  <xsl:template match="/">
    <html>
    <head>
      <title>Ancestor example</title>
    </head>

    <body>
      <ul>
        <xsl:apply-templates select="//file"/>
      </ul>
    </body>
    </html>
  </xsl:template>

  <xsl:template match="file">
    <li>
    <xsl:apply-templates select="ancestor::folder" mode="path"/>
    <xsl:value-of select="@name"/>
    </li>
  </xsl:template>

  <xsl:template match="folder" mode="path">
    <xsl:value-of select="@name"/>
    <xsl:text>/</xsl:text>
  </xsl:template>

</xsl:transform>

Resultaat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns:html="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Ancestor example</title>
  </head>
  <body>
    <ul>
    <li>home/martin/development/javahova/tutorial.xml</li>
    <li>home/martin/development/javahova/tutorial.xsl</li>
    <li>home/martin/uu/presentation.tex</li>
    </ul>
  </body>
</html>

Je ziet hoeveel fraaier deze oplossing werkt ten opzichte van het gebrabbel met die named templates :) . Nu nog maar hopen dat dit ongeveer is wat je wilde bereiken ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Mijn probleem is dus precies anders om :)

de namen staan niet in de node zoals in jouw voorbeeld, maar het zijn de namen van de nodes zelf..

zoals ik al probeerde aan te geven

als ik in group beland, dan wil ik achterhalen welke elementen ik gepasseerd ben..

zoals ik hier onder heb aangegeven: tussen de <!-- path --> tags
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<xml>
  <appl/>
  <group> <!-- path="/xml/group[0]/" -->
    <members>
      <appl/>
      <group> <!-- path="/xml/group[0]/members/group[0]/" -->
        <members>
          <appl/>
          <appl/>
        </members>
      </group>
      <appl/>
    </members>
  </group>
  <appl/>
  <group> <!-- path="/xml/group[1]/" -->
    <members>
      <appl/>
      <appl/>
    </members>
  </group>
  <appl/>
</xml>

dit alles is nodig omdat deze "path" weer terug komt in een hyperlink.. :)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Mwah het is niet echt andersom, maar een vrij triviale aanpassing van mijn voorbeeld. Ik heb een klein voorbeeld gemaakt, de posities mag je zelf gaan doen :+ .
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<xml>
  <appl/>
  <group> <!-- path="/xml/group[0]/" -->
    <members>
    <appl/>
    <group> <!-- path="/xml/group[0]/members/group[0]/" -->
      <members>
        <appl/>
        <appl/>
      </members>
    </group>
    <appl/>
    </members>
  </group>
  <appl/>
  <group> <!-- path="/xml/group[1]/" -->
    <members>
    <appl/>
    <appl/>
    </members>
  </group>
  <appl/>
</xml>


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0"?>

<xsl:transform version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns="http://www.w3.org/1999/xhtml"
            xmlns:html="http://www.w3.org/1999/xhtml">

  <xsl:output method="xml" indent="yes" encoding="UTF-8"
      doctype-public="-//W3C//DTD XHTML 1.1//EN"
      doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>

  <xsl:template match="/">
    <html>
    <head>
      <title>Ancestor example</title>
    </head>

    <body>
      <ul>
        <xsl:apply-templates select="//group"/>
      </ul>
    </body>
    </html>
  </xsl:template>

  <xsl:template match="group">
    <li>
    <xsl:apply-templates select="ancestor-or-self::*" mode="path"/>
    </li>
  </xsl:template>

  <xsl:template match="*" mode="path">
    <xsl:value-of select="name(.)"/>
    <xsl:text>/</xsl:text>
  </xsl:template>

</xsl:transform>


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns:html="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Ancestor example</title>
  </head>
  <body>
    <ul>
    <li>xml/group/</li>
    <li>xml/group/members/group/</li>
    <li>xml/group/</li>
    </ul>
  </body>
</html>

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Mijn Dank is zeer groot B-)

moet nog heel even puzzelen hoe ik dit verder implementeer.. omdat mijn group en members ook nog een verdere functionaliteit bevatten..

Als ik u ooit nog een wederdienst kan bieden, trek maar aan de bel :+ *D

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
P3nGu1N: moet nog heel even puzzelen hoe ik dit verder implementeer.. omdat mijn group en members ook nog een verdere functionaliteit bevatten..
Ik denk dat de opzet uitermate geschikt is voor speciale gevallen of uitbreidingen omdat het gewoon binnen het standaard mechanisme van XSLT blijft: het toepassen van templates. Dat zal dus als het goed is geen problemen opleveren :) .
Als ik u ooit nog een wederdienst kan bieden
Stel nog maar eens een vraag ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Stel nog maar eens een vraag ;) .
Freak (8> :P

Verwijderd

Topicstarter
Oke, dan nog maar een vraagje :)

het volgende werkt:
code:
1
2
3
4
5
6
7
<xsl:text disable-output-escaping="yes">&lt;A HREF='doodaXml:&lt;Application&gt;</xsl:text>
    <xsl:copy-of select="./ApplInput"/>
    <xsl:copy-of select="./ApplOutput"/>
    <xsl:copy-of select="."/>
    <xsl:text disable-output-escaping="yes">&lt;/Application&gt;</xsl:text>
    <xsl:copy-of select="./Access"/>
<xsl:text disable-output-escaping="yes">'&gt;Hyperlink&lt;/A&gt;</xsl:text>

en wat ik graag zou willen is zoiets:
code:
1
2
3
4
5
6
7
8
9
10
11
<A>
<xsl:attribute name="href">
    doodaXml:&lt;Application&gt;
    <xsl:copy-of select="./ApplInput"/>
    <xsl:copy-of select="./ApplOutput"/>
    <xsl:copy-of select="."/>
    &lt;/Application&gt;
    <xsl:copy-of select="./Access"/>
</xsl:attribute>
<xsl:text>Hyperlink</xsl:text>
</A>

Probleem is dat de 2de manier op de een of andere manier niet werkt..

hij geeft geen foutmeldingen ofzo.. maar de copy-of werkt dan niet.. als ik eerst een <xsl:text> open dan begint hij te zeuren dat er geen copy-of in text mag komen :(

waarom werkt de 2de manier niet :?

ps) zal toegeven dat de hyperlink niet er mooi wordt, maar dat is geen probleem.. :+

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Attributen kunnen alleen tekst bevatten en daarom is een copy-of eigenlijk zinloos. Wellicht dat het werkt als je een copy-of doet van tekst-nodes, maar of dat mogelijk is maakt eigenlijk niet omdat je toch gewoon value-of kan gebruiken in die gevallen.

Probeer anders eens om het resultaat eerst eens samen te stellen buiten een attribuut. Je hebt dan meer mogelijkheden, waardoor je kunt zien wat er fout gaat ipv dat je een foutmelding krijgt. Doordat je ziet wat er fout gaat, begrijp je dan beter wat de betekenis van je code is.

Die disable-output-escaping is zo ontzettend ranzig dat ik hem hier nooit meer wil zien! >:) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Wat is er mis met 'disable-output-escaping="yes"' Works fine :7

ik heb nog eens wat geprobeerd he..

als ik:
code:
1
<xsl:copy-of select="."/>

doe dan krijg ik wat ik wil.. maar dit moet in een hyperlink..

doe ik:
code:
1
2
3
4
5
6
7
<xsl:variable name="temp">doodaXml:<xsl:copy-of select="."/></xsl:variable>
<A>
  <xsl:attribute name="href">
    <xsl:value-of select="$temp"/>
  </xsl:attribute>
  Hyperlink
</A>

dan krijg ik wel de text van de copy-of, maar de structuur laat hij achterwege :?

WAAROM ;(

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
P3nGu1N: dan krijg ik wel de text van de copy-of, maar de structuur laat hij achterwege :?
Whow nu snap ik je pas. Je wilt de XML structuur in het attribuut? :o .

Dat kan niet op deze manier. XSLT is ontworpen als XML transformatie taal en heeft als input en output XML. Wat jij wilt, is XML structuur stoppen in een attribuut, wat helemaal geen XML structuur heeft. Je denkt dan heel erg in de syntax van XML en dan ben je inderdaad geneigd om te zeggen dat dit toch moet kunnen. Je werkt echter niet op de syntax, maar op het data-model van XML. Dit data-model staat geen structuur toe in een attribuut.

Als je een bepaalde XML achtige syntax nodig hebt in een attribuut om een of andere ranzige reden, zal je dat dus zelf moet afhandelen en dan mag je eventueel ook wel naar ranzige middelen grijpen omdat het toch al een ranzig zootje is :Y) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Tja, Live is a bitch >:)

dan maar op de vuile manier ;)
Pagina: 1