Toon posts:

[XML&XSL] Aan het worstelen met XML, XSL en schema's

Pagina: 1
Acties:
  • 124 views sinds 30-01-2008

Verwijderd

Topicstarter
Het probleem kort samengevat:

Ik wil hyperlinks in XML! En ja, ik ken XLinks, maar ik wou het graag helemaal zelf doen, zodat ik mijn eigen DTD kan gebruiken, als enige DTD.

Ik heb een eigen namespace, SmallTalk. Daaronder een onbepaalde hoeveelheid <Paragraph>-node's. En binnen die <Paragraph>-node's bevindt zich tekst en <Reference>-node's. Deze <Reference>-node's moeten omgezet worden naar HTML hyperlinks, maar binnen de context van hun parents.

Disclaimer: ;)

Ik neem aan dat XML onder "Programming & Webscripting" thuishoort, aangezien ik XSL gebruik, en XSL bestaat o.a. uit processing-instructions. Zoniet, excuses.

Ik heb al eens eerder geprobeerd met XML te werken, maar gaf het uiteindelijk op vanwege problemen die ik niet in staat was op te lossen. Natuurlijk heb ik eerst geprobeerd zelf oplossingen te vinden, maar ik ben daar niet in geslaagd. Als ik in mijn problemen het hele concept van XML mis, of voor niks mijn eigen taal gebruik, zeg het gerust, maar hou het constructief, wanneer mogelijk! ;) Ik hoop dat mijn vraagstellingen duidelijk zijn!

Mocht het enig verschil maken (vast...): Ik gebruik Xerces en Xalan, beide projecten van de Apache Group om mijn XML & XSL naar HTML om te zetten. Dus de pagina's die ik bekijk zijn al in HTMl omgezet, dit gebeurt niet in de browser.

Om sucesvol met de onderstaande code te werken moet ik een aantal <>'s escapen, maar dit zie je niet terug in de code, omdat je ze in het forum allemaal terug ziet als <>'s , sorry hiervoor. Wie bereid is te antwoorden snapt neem ik aan sowieso wel hoe het werkt.

Het probleem:

Als mijn root (Namespace toch?) SmallTalk (gewoon een leuke naam) is, en de children Paragraph's, met als mogelijke children Reference's:

<SmallTalk>
   <Paragraph> ... </Paragraph>
   <Paragraph> tekst
      <Reference Resource="..." Title="..." Description="...">...</Reference>
   tekst </Paragraph>
</SmallTalk>


Hoe kan ik dan alle <Reference>-nodes verwerken, zodat ze als html-links weergegeven worden? De enige methode die ik tot nu toe gevonden heb, templates aanroepen, werkt niet (zie hieronder). Aan de ene kant wel logisch hoor: alle <Reference>-node's worden verwerkt waar je zo'n template opvraagt. Maar hoe kan ik dan wel alle <Reference>-node's in place converteren???

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="SmallTalk/Title" /></title>
</head>
<body>

[b]<xsl:apply-templates select="SmallTalk/Paragraph" />
<xsl:apply-templates select="SmallTalk/Paragraph/Reference" />[/b]

</body>
</html>
</xsl:template>

[b]<xsl:template match="SmallTalk/Paragraph">
<p><xsl:value-of select="." /></p>
</xsl:template>

<xsl:template match="SmallTalk/Paragraph/Reference">
   <a href="<xsl:value-of select="@Resource" />" title="<xsl:value-of select="@Description" />">
      <xsl:value-of select="." />
   </a>
</xsl:template>
</xsl:stylesheet>[/b]


De output van dit stylesheet is:

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Testing, 1, 2, 3, ...</title>
</head>
<body>
<p>Dit is een test-link: XML.com in XML.</p>
&lt;a href="http://www.xml.com" title="..."&gt;XML.com&lt;/a&gt;
</body>
</html>


Dus de <Reference>-node's worden verwerkt na de <Paragraph>-node's, in plaats van binnen de <Paragraph>-node's, wat mijn doel is. Tot nu toe heb ik geen XSL-syntax kunnen vinden die ervoor zorgt dat de <Reference>-node's binnen de <Paragraph>-node's omgezet worden in HTML.

Iemand enig idee? Alle suggesties zijn welkom! Bij voorbaat mijn dank,

Peter Odding

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

djc

Volgens mij is je XSLT te restrictief. Mag ik een andere methode voorstellen?

Ik denk dat dit is wat je bedoelt:

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
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/SmallTalk">
<html>
<head>
<title><xsl:value-of select="Title" /></title>
</head>
<body>

<xsl:apply-templates />

</body>
</html>
</xsl:template>

<xsl:template match="Paragraph">
<p><xsl:apply-templates /></p>
</xsl:template>

<xsl:template match="Reference">
   <a href="{@Resource}" title="{@Description}" />"
      <xsl:value-of select="." />
   </a>
</xsl:template>

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

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

</xsl:stylesheet>

Rustacean


Verwijderd

Topicstarter
_/-\o_ Voorstel geaccepteerd _/-\o_

Ongelofelijk, dat ik hier dan twee lange nachten mee heb moeten worstelen... |:(

Ik zou zelf toch zeggen dat één van de meest vanzelfsprekende functies van XSL zou zijn om XML te vertalen naar (X)HTML. En toch ben ik hier lang naar op zoek geweest!

Hartstikke bedankt Manuzhai! Het werkte in één keer.

ps. Nou oké, niet in één keer ;), regel 22:
<a href="{@Resource}" title="{@Description}" />"
moet zijn
<a href="{@Resource}" title="{@Description}">

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

djc

Ja, dat komt omdat ik heb geedit vanaf jouw code, en die was nogal braque. :P

Snap je nu ook beter hoe je moet werken met templates?

[ Voor 28% gewijzigd door djc op 23-10-2004 14:09 ]

Rustacean


Verwijderd

Topicstarter
Ja en nee ;)

Ik ben al een stuk verder. Maar ik heb nog wel een paar problemen. Ik ben al veel verder wat betreft XSL-selectors, maar nog niet alles lukt... Misschien mis ik wel gewoon het overzicht om dit probleem orderlijk op te lossen.

Mocht je ergens een typfout of een onafgesloten tag tegenkomen, sorry, ik typ deze voorbeelden zelf in, vandaar. Mochten er echt fouten in mijn XML of XSL zitten dan vertelt Xalan me dat wel

Een voorbeeld van mijn XML (zonder indent omdat de layout dat niet zo leuk vindt :*)) :

<?xml version="1.0" encoding="ISO8859-1" standalone="no"?>
<!DOCTYPE Document SYSTEM "Document.dtd">
<Document Language="en-us" Text-direction="LTR">

<Metadata>
<Title Language="en-us">...</Title>
<Description Language="en-us">...</Description>
<Keywords Language="en-us">...</Keywords>
<Author Language="nl">...</Author>
<Copyright Language="en-us">...</Copyright>
</Metadata>

<Content>
<Post>
<Title>...</Title>
<Date>
<Day>...</Day>
<Month>...</Month>
<Year>...</Year>
<Time>...</Time>
</Date>
<Content>
<Paragraph>
<Reference Resource="..." Title="..." Description="...">...</Reference>
</Paragraph>
</Content>
</Post>
</Content>
</Document>


En een voorbeeld van mijn XSL (wederom zonder indent):

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/Document">
<html lang="{@Language}" dir="{@Text-direction}">
<head>
<xsl:apply-templates select="/Document/Metadata/Description" />
<title><xsl:apply-templates select="/Document/Metadata/Title" /></title>
</head>
<body>

<xsl:apply-templates select="/Document/Content/Post" />

</body>
</html>
</xsl:template>

<xsl:template match="/Document/Metadata/Title">
<xsl:value-of select="." />
</xsl:template>

<xsl:template match="/Document/Metadata/Description">
<META name="description" lang="{@Language}" content="{.}" />
</xsl:template>

<xsl:template match="/Document/Content/Post">
<xsl:for-each select=".">
<h2><xsl:value-of select="./Title" /></h2>
<p>
<i>
Posted on
<xsl:value-of select="./Date/Month" />/
<xsl:value-of select="./Date/Day"/>/
<xsl:value-of select="./Date/Year" />, at 
<xsl:value-of select="./Date/Time" />
</i>
</p>
<xsl:for-each select="./Content/Paragraph">
<p><xsl:value-of select="." /></p>
</xsl:for-each>
</xsl:for-each>
</xsl:template>

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

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

</xsl:stylesheet>


Ten eerste: ik neem zelf al aan dat de aanpak die je hierboven ziet, in mijn XSL, NIET de goede is. Ik zag alleen geen andere opties. Als ik bijvoorbeeld alleen de content onder Document/Content/Post wil weergeven, maar ik verwerk niet de Document/Content/Post/Date data, dan wordt deze gewoon AS IS in mijn HTML gepleurd. Komt dit door de twee laatste selectors, of de laatste, die jij hebt toegevoegd?

Een deel heb ik weggelaten, maar dit is waar het om draait. Wat je in je vorige post voorstelde, het gebruik van templates die ik dan aanroep van binnen de <body></body> tags, werkte eerder wel, maar om de een of andere reden nu niet meer.

Ik zag die templates als een soort van zoeken/vervangen voor het hele document. Maar blijkbaar zie ik dit verkeerd. Want zo werkt het niet. Als ik als match="Paragraph" gebruik, worden ze niet vervangen. Dus ikdacht dat ik misschien gewoon een andere selector nodig had. In een of andere tutorial was ik een -erg klein- overzichtje tegengekomen. Daar stond dat als ik match="Document/Content/Post//Paragraph" gebruikte, alle Paragraph's onder Post of een van zijn children werden verwerkt. Dit is niet het geval. Het lukt me gewoon niet om binnen mijn structuur, dus onder Document/Content/Post, alle <Paragraph>'s te vervangen door <p>'s.

Hoe kan ik dit wel doen? Ik heb al een paar uur via Google rondgesurft, op zoek naar "XSL selectors" en XSL tutorials in het algemeen. Maar ik wordt er niet veel wijzer van...

Of ik er nou uitkom of niet, in ieder geval heel erg bedankt voor de hulp die je al gegeven hebt!

Verwijderd

Topicstarter
ps. Mijn XSL is op het moment één grote chaos. Ik weet het. Dit komt omdat ik alle mogelijke methoden die ik tegenkom, uitprobeer. Vandaar. En dat ik redelijk nieuw ben in XML (een week ongeveer), laat staan XSL.

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

djc

Die laatste template zorgt er inderdaad voor dat onverwerkte nodes botweg worden gekopieerd. Als je dat niet wilt moet je die regel weghalen (ik gebruik hem altijd omdat ik op een bepaald niveau direct XHTML in mijn XML heb staan, en die mag dan gewoon verbatim gekopieerd worden).

Waar je volgens mij op moet letten is dat je veel minder moeilijk moet doen met je select-clauses. Denk veel meer lokaal in plaats van in de context van je hele document, kijk wat je omgeving op dat moment is en probeer aan de hand daarvan verder te gaan.

Verder ben je aan het prutsen met templates en for-each. In principe is
code:
1
2
3
<xsl:for-each select="crap">
   <xsl:value-of select="@attrib" />
</xsl:for-each>
hetzelfde als

code:
1
2
3
4
5
<xsl:apply-templates select="crap" />

<xsl:template match="crap">
   <xsl:value-of select="@attrib" />
</xsl:template>
, alleen maakt de tweede variant op een gegeven moment het onderhoud van je stylesheet veel makkelijker.

Het helpt IMHO om aan de XSLT te denken als een boom. Je begint met je root-element, dat je matcht. Daarvoor geef je dan een stuk output, waarin je telkens een stuk output voor een tak van de boom opneemt. Op dat moment moet je dus in de root een apply-templates doen (eventueel met opgave van het "soort" tak), en ergens anders een template hebben die voor die tak de output genereert.

Wat ik denk dat je bedoelt.

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
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/Document">
<html lang="{@Language}" dir="{@Text-direction}">
<head>
<xsl:apply-templates select="Description" /> <!-- Lokaal denken! -->
<title><xsl:value-of select="Metadata/Title" /></title> <!-- Waarom een hele template voor alleen maar deze waarde? -->
</head>
<body>

<xsl:apply-templates select="Content/Post" />

</body>
</html>
</xsl:template>

<xsl:template match="Description">
<meta name="description" lang="{@Language}" content="{.}" />
</xsl:template>

<xsl:template match="Post"> <!-- Die for-each is hier dus loos!!! -->
<h2><xsl:value-of select="Title" /></h2>
<p>
<i>
Posted on
<xsl:value-of select="Date/Month" />/
<xsl:value-of select="Date/Day"/>/
<xsl:value-of select="Date/Year" />, at 
<xsl:value-of select="Date/Time" />
</i>
</p>
<xsl:for-each select="Content/Paragraph">
<p><xsl:value-of select="." /></p>
</xsl:for-each>
</xsl:for-each>
</xsl:template>

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

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

</xsl:stylesheet>

Rustacean


Verwijderd

Topicstarter
Ehm, ik wordt gek. 8)7

Zelfs de officiële recommendation van XPath zegt dat de selector "//Child" elk element met de naam Child in het document selecteert. Volgens mij zou simpelweg "Child" dit ook moeten doen, maargoed.

Ik ben ff terug naar de basis, om het probleem op te lossen. Ik gebruik gewoon een helemaal gestripte DTD en XML, die allen toelaten wat ik nodig heb, en ik weet zeker dat het probleem niet hier ligt. Ook mij XSL heb ik gestript om het simpel te houden. Dit is mijn XSL-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
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/Document">
<html>
<head>
<title><xsl:value-of select="Title" /></title>
</head>
<body>

<xsl:apply-templates />

</body>
</html>
</xsl:template>

<!-- Als selector "Child" of "//Child" maakt geen verschil,
niet voor één van de twee templates, ook niet voor allebei -->
<xsl:template match="Paragraph">
<p><xsl:apply-templates /></p>
</xsl:template>

<xsl:template match="Reference">
   <a href="{@Resource}" title="{@Description}">
      <xsl:value-of select="." />
   </a>
</xsl:template>

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

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

</xsl:stylesheet>


Zie regel 17. Als ik dit stylesheet over mijn xml haal, worden alleen de <Paragraph>-elementen verwerkt. En als ik in mijn XSL de volgorde van de templates verander, maakt dit niks uit. Alleen door het template voor <Paragraph>-elementen tussen <!-- comment-tags --> te zetten, worden <Reference>-elementen verwerkt.

Ik dacht: alle <Reference>-elementen staan binnen <Paragraph>-elementen, dus vandaar dat ze niet verwerkt worden. Maar hoe kom ik dan om dit probleem heen???

Sorry hoor, het lijkt gewoon zo simpel en logisch op al die sites die je enthousiast maken over het gebruik van XML in combinatie XSL. Maar als een simpele constructie als deze (volgens mij?) al niet werkt, wordt het moeilijk met XML.

Edit:
code:
1
2
3
<xsl:template match="*">
    <xsl:copy-of select="."/>
</xsl:template>


onder (na?) de twee templates in het XSL-stylesheet werkt ook niet, maar dat had ik wel verwacht.

[ Voor 18% gewijzigd door Verwijderd op 24-10-2004 19:16 ]


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

djc

Het is ook niet zo heel moeilijk, jij zit gewoon te prutsen.

Maak ergens een dir met daarin een XML, een XSL en de XHTML die je eruit wil hebben, dan kan ik er nog eens goed naar kijken. Of voeg me toe op MSN ofzo.

[ Voor 7% gewijzigd door djc op 24-10-2004 22:41 ]

Rustacean


Verwijderd

Topicstarter
Nog bedankt voor je hulp Manuzhai! Ondertussen zijn mijn problemen opgelost. Ik snapte de logica gewoon niet.

Als een element nog children heeft die verwerkt moeten worden, moet er dus in de template voor dat element ook een <xsl:apply-templates/> gebruikt worden. Dit is ondertussen <xsl:apply-templates mode="Body" select="node()"/> geworden omdat ik weet hoe mode's werken, en dat je de selector node() kunt gebruiken voor alle elementen binnen het huidige element.

Nogmaals bedankt!

EDIT: Ik upload de bestanden dus niet, aangezien het niet meer nodig is... :)

[ Voor 13% gewijzigd door Verwijderd op 27-10-2004 19:37 ]


  • airliner
  • Registratie: Juni 2002
  • Laatst online: 26-03 11:55

airliner

Swell

ik heb ongeveer hetzelfde probleem, maar dan anders :9

dit is een simpele versie van mijn xml bestand (bestand.xml):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="bestand.xsl"?>
<a>
  <b>
   <c>
     <nummer>1</nummer>
     <beschrijving url="http://www.tweakers.net/">Tweakers.net</beschrijving>
   </c>
  </b>
  <b>
   <c>
     <nummer>2</nummer>
     <beschrijving url="http://gathering.tweakers.net/">GoT</beschrijving>
   </c>
  </b>
  <content>
    <title>Pagina titel</title>
  </content>
</a>


en dit is het xsl bestand (bestand.xsl):
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
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="a">

    <html>

      <head>
        <title><xsl:value-of select="content/title"/></title>
      </head>

      <body>

        <table>
        <xsl:for-each select="b/c">
        <xsl:sort select="nummer"/>
        <xsl:if test="nummer &gt; 0">
          <tr>
            <td><xsl:value-of select="nummer"/></td>
            <td><a href="{@url}"><xsl:value-of select="beschrijving"/></a></td>
          </tr>
        </xsl:if>
        </xsl:for-each>
        </table>

      </body>
    </html>

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


xsl:if is alleen van toepassing op het originele bestand, hier is het een beetje nutteloos

mijn vraag is deze: hoe krijg ik die url werkende?
href="{@url}" werkt niet
href="{beschrijving@url}" werkt niet :X

ik kan ook nergens documentatie vinden over {@...} voor een attribute in xsl (w3schools/google)

[ Voor 22% gewijzigd door airliner op 12-01-2006 18:51 ]


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:29

Creepy

Tactical Espionage Splatterer

En daar kick je een topic uit 2004 voor? Right ;)

Anyway, je bent nogal kort van stof wat beterft je vraag en informatie. Dus welke zaken heb je nu zelf al geprobeerd? Wat bedoel je met "werkt niet". Wat heb je allemaal nog meer geprobeerd.
Zie ook P&W FAQ - De "quickstart" zodat je weet wat we eigenlijk van je verwachten voordat je hier een vraag stelt.
Dit topic sluit ik nu. Open gerust een nieuw topic mits je kan aangeven wat je nu zelf al hebt geprobeerd etc (dus let op die quickstart :) ).

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney

Pagina: 1

Dit topic is gesloten.