Toon posts:

[XSL] Valid XHTML transformen lukt me niet :-(

Pagina: 1
Acties:
  • 103 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Hallo allemaal! Ik heb GOT al eerder geterroriseerd met n00b vragen over XSL. Gelukkig ben ik ondertussen al heel wat verder met XSL, maar ik heb nu een probleem waar ik toch echt niet uit kom in mijn eentje.

Een inleidingetje :*)

Ik verwerk XML bestanden met mijn eigen dialectje (enigzins te vergelijken met XHTML) via XSL tot XHTML, die dan vervolgens naar mijn webhost verstuurd wordt. Omdat ik met X-Links en aanverwanten niet verder kwam, heb ik "mijn eigen hyperlink standaard" gemaakt, die dan omgezet wordt tot gewone XHTML.

Een van de functies van de xsl template die deze links omzet --waar ik erg blij mee ben-- is dat er onderscheid gemaakt wordt tussen interne en externe links, en dat anchors herkend worden. Op deze manier krijgen alle links op mijn web site een tooltip die bijvoorbeeld een van de volgende beschrijvingen bevat:

Interne link naar anchor "blaat" op pagina "blaat.html"
Interne link naar anchor "blaat" op deze pagina
Interne link naar bestand "blaat.zip"
Externe link naar "http://www.host.com/bestand.extensie"

En het probleem is...

Als mijn XSL stylesheet de pagina's verwerkt, krijgen alle links die voortkomen uit mijn XML bestanden deze tooltips, maar de links in het menu bijvoorbeeld niet. Dit is natuurlijk logisch, ik voeg het menu namelijk via datzelfde XSL bestand toe.

Omdat ik geen zin had om dubbel werk te doen, dacht ik slim te zijn: gewoon mijn originele links (eigen XML dialect) laten staan, en de links in het menu ook toevoegen in ditzelfde formaat, om vervolgens met een tweede stylesheet alle links te transformen. Ik transform immers toch naar XHTML, en XHTML zou even goed te verwerken moeten zijn als XML (ja, de pagina's zijn volledig gevalideerd ;)).

Maar als ik met mijn tweede stylesheet de XHTML pagina's transform gebeurt er gewoon niks :(. De transform duurt wel eeuwenlang (alleen het laden van het stylesheet duurt 20 tot 30sec), maar de pagina's veranderen geen bit. Nou oke, misschien wordt er wat whitespace gestript ;).

Hieronder volgt (het|de)? stylesheet in kwestie, dit is dus degene die de XHTML pagina's verwerkt:

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" version="1.0" omit-xml-declaration="yes" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

<xsl:template match="reference">
    <xsl:choose>
        <xsl:when test="@type = 'extended'">
            <xsl:choose>
                <xsl:when test="@anchor">
                    <xsl:choose>
                        <xsl:when test="not(@page)">
                            <a href="#{@anchor}" title="Internal link to anchor &quot;{@anchor}&quot; on this page" onmouseover="self.status='Internal link to anchor &quot;{@anchor}&quot; on this page'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                        </xsl:when>
                        <xsl:otherwise>
                            <a href="{@page}.html#{@anchor}" title="Internal link to anchor &quot;{@anchor}&quot; on page &quot;{@page}.html&quot;" onmouseover="self.status='Internal link to anchor &quot;{@anchor}&quot; on page &quot;{@page}.html&quot;'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:otherwise>
                    <a href="{@page}.html" title="Internal link to page &quot;{@page}.html&quot;" onmouseover="self.status='Internal link to page &quot;{@page}.html&quot;'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:when test="@type = 'simple'">
            <xsl:choose>
                <xsl:when test="@anchor">
                    <a href="{@url}#{@anchor}" title="External link to anchor &quot;{@anchor}&quot; on page &quot;{@url}&quot;" onmouseover="self.status='External link to anchor &quot;{@anchor}&quot; on page &quot;{@url}&quot;'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:choose>
                        <xsl:when test="(starts-with(@url, 'http://')) or (starts-with(@url, 'ftp://')) or (starts-with(@url, 'https://'))">
                            <a href="{@url}{@anchor}" title="External link to &quot;{@url}&quot;" onmouseover="self.status='External link to &quot;{@url}&quot;'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                        </xsl:when>
                        <xsl:when test="starts-with(@url, 'mailto:')">
                            <a href="{@url}" title="Open default mail-client with new message to &quot;{substring-after(@url,':')}&quot;" onmouseover="self.status='Open default mail-client with new message to &quot;{substring-after(@url,':')}&quot;'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                        </xsl:when>
                        <xsl:otherwise>
                            <a href="{@url}{@anchor}" title="Internal link to file &quot;{@url}&quot;" onmouseover="self.status='Internal link to file &quot;{@url}&quot;'; return true;" onmouseout="self.status=''; return true;"><xsl:apply-templates/></a>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:when test="@type = 'anchor'">
            <a id="{@id}" name="{@id}" title="{@id}"><xsl:apply-templates/></a>
        </xsl:when>
        <!-- Dit is gewoon een vuile hack, zodat ik vannacht het idee kon noteren zonder er nog lang mee bezig te hoeven zijn. -->
        <xsl:when test="@type = 'weblogpost'">
            <a id="{@id}" name="{@id}" rel="bookmark" href="{@href}" title="Link to this post (for bookmarking &amp; linking)"><xsl:apply-templates/></a>
        </xsl:when>
    </xsl:choose>
</xsl:template>

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

<xsl:template match="*">
<xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>


Dat dit stylesheet nogal lang draait is neem ik aan ook wel logisch vanwege de grote choose/when/otherwise constructie. De rest van de inhoud van de pagina's wordt netjes gekopieerd, maar er veranderd niks... Ik vindt dus in mijn XHTML output dezelfde <reference> elementen terug. Er worden overigens geen foutmeldingen of waarschuwingen weergegeven.

Ik gebruik overigens Apache Ant, met geintegreerde XSL taak. Dit is natuurlijk de combinatie Xerces en Xalan.

Heeft iemand enig idee hoe dit komt??

- Peter Odding

ps. Ik neem aan dat er heel wat aan te merken is op dit stylesheet, elk commentaar (constructief zou mooi zijn) is dan ook welkom. Vergeet aub niet dat ik nog niet lang met XSL bezig ben, en misschien gewoon iets stoms over het hoofd heb gezien... Alvast bedankt!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Omdat je een xsl:template voor alle elementen (*) hebt, wordt deze template toegepast op het document element (html) en wordt daarvan dus een kopie gemaakt naar de output. De transformer komt dus nooit toe aan het toepassen van de reference template. 't Is een hele goeie XSL-oefening om daar uit te komen zonder hulp van anderen ;)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Topicstarter
Okee,

DOH!!!!!!!!!!!!!!!!!!!!!!!!

Bedankt :)

Hehe, ongelofelijk, daar ben ik dan 2 uur ofzo naar op zoek geweest. Echt ongelofelijk.

Gelukkig voelde ik het al aankomen en was er de disclaimer "en misschien gewoon iets stoms over het hoofd heb gezien...". Hehe.

[ Voor 80% gewijzigd door Verwijderd op 07-02-2005 16:06 ]


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Om echt valid xhtml te kunnen genereren met XSL moet je eigenlijk met versie 2 van de taal werken. De method kun je dan ook op xhtml zetten, die net even anders werkt dan de xml modus. Dit omdat de parser anders van
code:
1
<script type="text/javascript" src="script.js"></script>

dit maakt:
code:
1
<script type="text/javascript" src="script.js" />


wat dus niet valid is, en zelfs zorgt dat de gehele pagina niet gerenderd wordt. Tis maar even dat je het weet, als je hier problemen mee gaat krijgen.

Dit gebeurt overigens met alle lege elementen. Dus ook tabelcellen, paragraven etc.

[ Voor 33% gewijzigd door Michali op 07-02-2005 16:27 ]

Noushka's Magnificent Dream | Unity


Verwijderd

Topicstarter
Hehe, bedankt, dit probleem was ik zelf ook al tegen gekomen. Mijn hack was escapen als cdata. Maar inderdaad, XSL 2.0 schijnt al aardig wat verbetert te zijn t.o.v. XSL 1.0. Ben even snel op zoek geweest, maar ken je ook Java XSL processors? Blijf het liefst platform onafhankelijk, maar ik vindt nergens iets over Xalan en 2.0 ondersteuning :|.

Maaruh, ik kwam net hier terug om toch nog even door te vragen. Volgens mij mis ik een klikje in m'n hoofd ;).

Ik wil eigenlijk gewoon de pagina kopieeren natuurlijk, maar dus wel eerst alle <reference> elementen verwerken. Is dit onmogelijk zonder templates aan te maken voor alles wat <reference> elementen kan bevatten? Dat is natuurlijk nogal loos, de pagina's bevatten een volledige layout, dan ben ik eeuwen bezig met mijn XSL stylesheet, en kan ik hem bij de eerste redesign waarschijnlijk weer veranderen....

Ik kan me niet voorstellen dat er geen simpelere methode is, maar op het moment zie ik hem niet...

Please enlighten me! :)

EDITje:

code:
1
2
3
4
5
6
7
8
9
10
<xsl:template match="*">
    <xsl:choose>
        <xsl:when test="name() = 'reference'">
            <!-- Veel choose when/otherwise code - zie vorige code, loos om te herhalen -->
        </xsl:when>
    <xsl:otherwise>
        <xsl:copy-of select="." />
    </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Had stilletjes gehoopt dat dit zou werken, maar ook deze haalt niks uit. Volgens mij zie ik nog steeds iets over het hoofd :(.

[ Voor 20% gewijzigd door Verwijderd op 07-02-2005 18:53 ]


  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Aangenomen dat je reference elementen allemaal zijn opgenomen in een root-element zou het helpen als je een template maakt die dat root-element matcht en vervolgens alleen apply-templatest...

Rustacean


Verwijderd

Ik begin te vermoeden dat je op zoek bent naar een XSL stylesheet die alle elementen van de input-XML kopieert naar de output BEHALVE eentje (of enkele).

En die ene (of die paar enkele), daar moet 'iets' mee gebeuren.

Nou, da's een standaard probleem - en daar is dus ook een standaard oplossing voor.
En die is te vinden in zowat elke XSLT-faq, dus ga ik 'm hier niet intypen.

Hint: kijk eens naar xsl:copy, xsl:copy-of en bedenk dat stylesheets hierarchisch werken, maw je maakt een xsl:copy voor "alles" en een apart template voor het elk element waarmee 'iets' moet gebeuren.

Kleur de plaatjes en maak dit verhaal zelf af.

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

peter.o:
Blijf het liefst platform onafhankelijk, maar ik vindt nergens iets over Xalan en 2.0 ondersteuning :|.
Kijk eens naar Saxon.
code:
1
2
3
4
5
6
7
8
9
10
<xsl:template match="*">
    <xsl:choose>
        <xsl:when test="name() = 'reference'">
            <!-- Veel choose when/otherwise code - zie vorige code, loos om te herhalen -->
        </xsl:when>
    <xsl:otherwise>
        <xsl:copy-of select="." />
    </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Had stilletjes gehoopt dat dit zou werken, maar ook deze haalt niks uit. Volgens mij zie ik nog steeds iets over het hoofd :(.
Je maakt hier exact dezelfde fout als in je eerste sheet, maar nu doe je het alleen 1 niveautje lager. De reden dat ik eerder al zei dat het een goeie oefening is om dit in XSL voor elkaar te krijgen is, omdat 't namelijk je dwingt op de xsl-manier te denken, i.p.v. de imperatieve "programmeer"-manier. 't Is misschien een beetje flauw dat ik je de oplossing niet vertel, maar ik ben het wat dat betreft wel met saghws eens; 't is ook wel te vinden als je geen zin hebt 't zelf uit te pluizen ;)

edit:
hint: http://www.w3.org/TR/1999/REC-xslt-19991116#copying

[ Voor 11% gewijzigd door drm op 08-02-2005 15:08 ]

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Topicstarter
Ben er ondertussen uit. Bedankt voor jullie hulp. Jullie hebben inderdaad gelijk dat dit alles opzich nog al standaard is. Toch heb ik wel degelijk veel gezocht, en verschillende XSL faq's doorgebladerd. Uiteindelijk bleek dat het dus ging om het feit dat ik niet <reference> moet matchen, maar xhtml:reference, omdat mijn source XHTML is, en dus ook alle nodes van <html> onder deze namespace leven.

Nogmaals bedankt!

- Peter Odding
Pagina: 1