[xslt] Rare uitvoer waar dat niet zou moeten

Pagina: 1
Acties:

  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
Voor een programma om kostenmodellen door te rekenen ben ik bezig een XSL te schrijven die de geexporteerde XML omzet naar een tab of comma-separated formaat. Als invoer heb ik dit bestand: http://dev.trag.nl/meuk/pgxml.xml. Ik gebruik de volgende XSL:

XML:
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
<?xml version='1.0' ?>

<!-- This line tells the transformer what version of XSLT we're using -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:qpr="www.qpr.com">
    <xsl:strip-space elements="*" />
    
    
    <!-- Tell the transformer that we're outputting text -->
    <xsl:output  method="text" encoding="ASCII" version='1.0' omit-xml-declaration="no" media-type="text/plain" />
    
    <!-- for each ModelElement.... -->
    <xsl:template match="ModelElement">
    
        <!-- Flows only... -->
        <xsl:if test="substring(@TypeID,4,2)='FL'">
            <!-- All text we want to output should be between xsl:text tags -->
            <xsl:text>__FLOW    </xsl:text>
            <xsl:value-of select="@ElementName"/>
            
            <!-- tab -->
            <xsl:text>  </xsl:text>
            <xsl:value-of select="Attribute[@AttributeName='From']/Record/Field[@Name='ElementName']/@Value"/>
            
            <!-- another tab -->
            <xsl:text>  </xsl:text>
            <xsl:value-of select="Attribute[@AttributeName='To']/Record/Field[@Name='ElementName']/@Value"/>
            
            <!-- &#10 is the code for a newline --> 
            <xsl:text>
</xsl:text>
        </xsl:if>
        
        <!-- objects only... -->
        <xsl:if test="substring(@TypeID,4,2)='PS' ">
        <xsl:text>__OBJECT  </xsl:text>
        <xsl:value-of select="@ElementName"/>
        <xsl:value-of select="concat('  ',normalize-space(Attribute[@AttributeName='Description']/Value))"/>
        <xsl:text>  </xsl:text>
        <xsl:value-of select="Attribute[@AttributeName='Organization items']/Record/Field[@Name='ElementName']/@Value"/>
        
        <xsl:text>
</xsl:text>
        </xsl:if>       
    </xsl:template>
</xsl:stylesheet>


Als ik dit echter ga transformen met msxsl (standaard tooltje voor de MSXML sdk) krijg ik er dit uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Costitem 020falsetrue0d 00:00:000d 00:00:00ConstantConstantAny incoming flowAll
outgoing flows0falseProduct 010falsetrue0d 00:00:000d 00:00:00ConstantConstantAn
y incoming flowAll outgoing flows0falseProduct 020falsetrue0d 00:00:000d 00:00:0
0ConstantConstantAny incoming flowAll outgoing flows0falseResource 010falsetrue0
d 00:00:000d 00:00:00ConstantConstantAny incoming flowAll outgoing flows0falseRe
source 020falsetrue0d 00:00:000d 00:00:00ConstantConstantAny incoming flowAll ou
tgoing flows0falseActiviteit 010falsetrue0d 00:00:000d 00:00:00ConstantConstantA
ny incoming flowAll outgoing flows0falseCostitem 010falsetrue0d 00:00:000d 00:00
:00ConstantConstantAny incoming flowAll outgoing flows0falsefalse0falseConstant0
d 00:00:00Constant0d 00:00:00false0false0falseConstant0d 00:00:00Constant0d 00:0
0:00false0false0falseConstant0d 00:00:00Constant0d 00:00:00false0false0falseCons
tant0d 00:00:00Constant0d 00:00:00false0false0falseConstant0d 00:00:00Constant0d
 00:00:00false0false0falseConstant0d 00:00:00Constant0d 00:00:00false0Single Val
ueNoned hh:mm:ssfalsetrueSingle ValueNone1234.57$falsetrueStart and End ValueNon
edd/MM/yyyy hh:mm:ssfalsetrueSingle ValueNone1234.57$falsetrue[Empty][Empty][Emp
ty][Empty]Other00000000d 00:00:00Hour


Het gekke is, dat als ik als XSL het volgende gebruik, het nog steeds deze gekke tekst output:

XML:
1
2
3
4
5
6
7
8
9
<?xml version='1.0' ?>

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

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

</xsl:stylesheet>


Wat is hier aan de hand? Het laatste voorbeeld zou toch helemaal niets moeten outputten?

edit:

tot zover de layout....

[ Voor 13% gewijzigd door MisterData op 07-07-2003 15:25 ]


  • tomato
  • Registratie: November 1999
  • Niet online
MisterData schreef op 07 July 2003 @ 15:25:
Als ik dit echter ga transformen met msxsl (standaard tooltje voor de MSXML sdk) krijg ik er dit uit:

[knip]
En wat wil je eruit krijgen, wat is hier niet goed aan?
Wat is hier aan de hand? Het laatste voorbeeld zou toch helemaal niets moeten outputten?
Jawel, dit is weer een aardig voorbeeld waar je geen rekening houdt met de default templates ;)

  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
tomato schreef op 07 July 2003 @ 15:46:
[...]

En wat wil je eruit krijgen, wat is hier niet goed aan?
Ik wil eruit krijgen wat de XSL vertelt dat de transformer moet uitspugen....
[...]

Jawel, dit is weer een aardig voorbeeld waar je geen rekening houdt met de default templates ;)
default templates?

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

drm

f0pc0dert

Het probleem is dat je nergens een <xsl:apply-templates /> doet. De processor transformeert de input dan niet, maar geeft de input gewoon door als output.
edit:
De "default template" dus :) "doorgeven" heet'ie :+


Omdat je hebt gezegd dat je output-method "text" is, worden alle elementen eruit gesloopt en alleen de characterdata van de input ge-output. Kortom: je output is alle characterdata uit je xml input. Ga maar na :)

edit:
In je tweede voorbeeld is dit wat verwarrend, zie ik..

In het tweede voorbeeld is iets dergelijks aan de hand, namelijk dat er expliciet aangegeven wordt dat de default template uitgevoerd moet worden. Wederom is de default-template het outputten van je characterdata en dus heb je hetzelfde resultaat.

[ Voor 35% gewijzigd door drm op 07-07-2003 16:00 ]

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


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
drm schreef op 07 July 2003 @ 15:50:
Het probleem is dat je nergens een <xsl:apply-templates /> doet. De processor transformeert de input dan niet, maar geeft de input gewoon door als output.
edit:
De "default template" dus :) "doorgeven" heet'ie :+


Omdat je hebt gezegd dat je output-method "text" is, worden alle elementen eruit gesloopt en alleen de characterdata van de input ge-output. Kortom: je output is alle characterdata uit je xml input. Ga maar na :)
OK, dus ik voeg dit toe:

XML:
1
2
3
    <xsl:template match="/">
        <xsl:apply-templates select="/ModelElements/ModelElement"/>
    </xsl:template>


Nu krijg ik helemaal geen output. Als ik het select-attribuut weghaal, krijg ik hetzelfde als ik al had...

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

drm

f0pc0dert

Kijk, je moet allereerst aangeven dat je de templates die er zijn toegepast wilt hebben op de tree die je als input hebt.

Dus een <xsl:apply-templates /> is uberhaupt van toepassing. Dan geef je vervolgens die <xsl:template> ... </xsl:template> voor de root op, en moet het werken.

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


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
drm schreef op 07 July 2003 @ 16:06:

[..]
Dan geef je vervolgens die <xsl:template> ... </xsl:template> voor de root op, en moet het werken.

Wat bedoel je hier precies mee?

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

drm

f0pc0dert

Precies het stukje wat je zelf zegt :)

Je geeft tenslotte het volgende aan:
code:
1
<xsl:template match="/"> ... </xsl:template>

wat zo goed als het volgende betekent:
Ik heb hier een template die je toe moet passen als je de root ( "/" ) tegenkomt

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


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
Ik weet niet zeker of dit is wat je bedoelt, maar zo werkt het iig niet:
code:
1
2
3
4
5
6
7
8
9
10
<xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <!-- for each ModelElement.... -->
    <xsl:template match="ModelElement">


                .....
                </xsl:template>


:/

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

drm

f0pc0dert

Waarom laat je nu opeens select="/ModelElements/ModelElement" weg uit de apply-templates match="/" :?

Kijk: de xslt processor loopt alleen die elementen langs die in de "huidige" node voorkomen. Dat betekent dus dat wanneer je niet expliciet opgeeft dat de parser een element dieper moet gaan (door een apply-templates te doen) dit dus ook niet gebeurt.

Kijk eens naar het volgende voorbeeld:
XML:
1
2
3
4
5
<root>
   <child>
      <grand-child></grand-child>
   </child>
</root>


met een xsl sheet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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="/">
      <xsl:apply-templates />
   </xsl:template>
   
   <xsl:template match="root">
      root element
   </xsl:template>

   <xsl:template match="child">
      child element
   </xsl:template>

   <xsl:template match="grand-child">
      grand-child element
   </xsl:template>
</xsl:stylesheet>


Dan zie je dat de output enkel die van de template van "root" is, omdat je alleen bij het hoogste niveau (bovenaan, "/" ) opgegeven hebt dat je een "niveautje dieper" wilde gaan. Een apply-templates doet niets anders dan zeggen:
"ga nu maar de templates toepassen voor de elementen die je op het huidige niveau tegenkomt"
tenzij je een expliciete "select" opgeeft waarbij je zegt:
Ga nu de templates toepassen voor de elementen die aan deze xpath-query voldoen
Als je dus in bovenstaand voorbeeld dieper de xml-boom wilt "verkennen" zal je dus aan de processor moeten vertellen dat je inderdaad de boom verder in wilt door een apply-templates "opdracht" te geven.

't Is niet echt een opdracht, maar dat is tenminste begrijpelijk (denk ik :+)

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


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
OK, ik heb je voorbeeld gelezen en ik snap 't ook (denk ik..). Ik heb nu het volgende gebakken:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    <xsl:template match="/">
        <xsl:apply-templates select="Model"/> <!-- !!!! -->
    </xsl:template> 

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

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

    <!-- for each ModelElement.... -->
    <xsl:template match="ModelElement">


Dit voorbeeld produceert helemaal geen output.....

edit:
Sorry for being n00b, ik heb hier al de hele dag aan gewerkt en het wil nog steeds niet....

[ Voor 25% gewijzigd door MisterData op 07-07-2003 17:06 ]


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

drm

f0pc0dert

Er is opzich niets op tegen om in je "/" template al te selecten op modelelement, hoor. Het probleem was alleen dat jij er van uit ging dat een template uberhaupt maar toegepast wordt als een element in de te transformeren xml-boom voorkwam, en dat is een misvatting.

Zoiets:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<xsl:template match="/">
   <!--
      Pas de templates toe die toepasbaar zijn op de elementen die
      voldoen aan de xpath-query aangegeven in select=""
   -->
   <xsl:apply-templates select="Model/ModelElements/ModelElement" />
</xsl:template>

<!--
   Deze template is toepasbaar op elk element dat ModelElement heet
-->
<xsl:template match="ModelElement">
   Yay, modelelement gevonden! <b>WOEI!</b><br />
   De inhoud is:<pre><xsl:value-of select="./text()" /></pre>
</xsl:template>

Ik kan me voorstellen dat 't verwarrend is, maar 't kwartje moet volgens mij gewoon even vallen :)

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


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
MD: lol XSLT is echt iets dat je ineens begrijpt - bij mij duurde het ook een dagje maar nu gaat het goed. Geef ons een deel van je source data want lijkt me gewoon dat je root geen model child nodes heeft...

  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
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 version='1.0' ?>

<!-- This line tells the transformer what version of XSLT we're using -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:qpr="www.qpr.com">
<xsl:template match="/">
   <!--
      Pas de templates toe die toepasbaar zijn op de elementen die
      voldoen aan de xpath-query aangegeven in select=""
   -->
    blegh.
   <xsl:apply-templates select="Model/ModelElements/ModelElement" />
</xsl:template>

<!--
   Deze template is toepasbaar op elk element dat ModelElement heet
-->
<xsl:template match="ModelElement">
   Yay, modelelement gevonden! <b>WOEI!</b><br />
   De inhoud is:<pre><xsl:value-of select="./text()" /></pre>
</xsl:template>
    

</xsl:stylesheet>

Geeft alleen maar 'blegh' als output.....

[ Voor 19% gewijzigd door MisterData op 07-07-2003 17:43 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
hobbit_be schreef op 07 juli 2003 @ 17:21:
MD: lol XSLT is echt iets dat je ineens begrijpt - bij mij duurde het ook een dagje maar nu gaat het goed. Geef ons een deel van je source data want lijkt me gewoon dat je root geen model child nodes heeft...
Zie openingspost, daar staat een link naar de source xml.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
nou ziet er mij nogtans picobello uit - wat bedoel je met 'bleh' ;) als je

code:
1
2
<xsl:output mode="text"/> nog aanstaat dan krijg je vast bleh anders
<xsl:output mode="xml"/>

  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
hobbit_be schreef op 07 July 2003 @ 17:41:
nou ziet er mij nogtans picobello uit - wat bedoel je met 'bleh' ;) als je

code:
1
2
<xsl:output mode="text"/> nog aanstaat dan krijg je vast bleh anders
<xsl:output mode="xml"/>
Whoops, ik had in de xsl die ik net posttte iets vergeten. Kijk nog maar een keer en zie dat ik ergens blegh heb neergezet (om te checken of die template wel werd aangeroepen...)

Het veranderen van de output method heeft geen zin, in beide gevallen krijg ik dezelfde uitvoer.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
nou ik heb het gevonden - jij defineert een xmlns die nou ik weet niet wat er mis mee is - ben geen held met namespaces (giggle) maar als je die in je source wegdoet gaat ie vlot.

  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
hobbit_be schreef op 07 juli 2003 @ 17:58:
nou ik heb het gevonden - jij defineert een xmlns die nou ik weet niet wat er mis mee is - ben geen held met namespaces (giggle) maar als je die in je source wegdoet gaat ie vlot.
Mag ik je heel hartelijk danken _/-\o_

Nu zit ik nog met 1 probleem (misschien dat drm wel held is in namespaces): ik heb in die source XML dus staan (bij die Model-tag) xmlns="www.qpr.com". Nou wil ik dit laten staan (als ik het weghaal werkt het) want ik wil die XSL rechtstreeks gebruiken op de XML die wordt uitgespuugd door de applicatie. Hoe vertel ik de XSL dat 'ie als namespace ook www.qpr.com moet gebruiken (want dan zal het wel werken...)?

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

drm

f0pc0dert

Ik vroeg me al af waarom je daar naar verwees 8)7 Heb er niet aan gedacht dat dat een oorzaak zou kunnen zijn...

Ik vraag me dat dus nog steeds af: waarom wil je qpr.com als namespace hebben, want je gebruikt 't ook nergens als prefix?

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


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
drm schreef op 07 juli 2003 @ 22:00:
Ik vroeg me al af waarom je daar naar verwees 8)7 Heb er niet aan gedacht dat dat een oorzaak zou kunnen zijn...

Ik vraag me dat dus nog steeds af: waarom wil je qpr.com als namespace hebben, want je gebruikt 't ook nergens als prefix?
Het bronbestand heb ik niet zelf gemaakt, dat is output van een programma. Omdat we voor een ander programma CSV/tab input willen hebben, moet ik een XSL schrijven om die XML om te zetten. In dat programma kun je als optie een XSL aanklikken die de XML die wordt geexporteerd omzet naar een ander formaat en dan pas opslaat. Ik kan dus niet zomaar die namespace weghalen....

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
hmm nu ben ik dat eens gaan bekijken en ik denmk dat ik een 'inkling' heb. hij defs

code:
1
xmlns="www...fff"


maar dit (Denk ik) redefinieert de default namespace. ie: je geeft geen prefix -
als ik er : xmlns:gator="www.gator.org" van maak lukt het weer.

zie ook:

http://www.dpawson.co.uk/xsl/sect2/N5536.html

idd te maken dat je geen prefix hebt en dat die wel nodig is. want door die default gaat geen enkele van jouw 'match' werken. In feite is elke element in jouw xml document eigenlijk:


code:
1
qpr:Model/qpr:ModelElement/...


als je je match dus zo zet werkt ie wel. vergeet ook niet de xmlns:qpr=... in je
stylesheet def te zetten. Er is vast een methode om tegen xslt te zeggen dat ie alle namen zelf moet prefixen met qpr: maar ik ben er nog niet achter... maar nu kun je alvast verder

edit:
nu werkt mijn xslt ineens ook ;) perfetto...

edit2:
volgens mij MOET je dus overal qpr: voor je match gaan zetten - zover ik het begrijp kun je het pas wegkrijgen in XSLT2.

[ Voor 71% gewijzigd door hobbit_be op 08-07-2003 11:42 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
Onhandig zeg... maar nu werkt het!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Zie ook het default-xpath-namespace attribuut in XSLT 2.0:

http://www.w3.org/TR/xslt20/#unprefixed-qnames

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


  • MisterData
  • Registratie: September 2001
  • Laatst online: 19:41
mbravenboer schreef op 08 July 2003 @ 13:18:
Zie ook het default-xpath-namespace attribuut in XSLT 2.0:

http://www.w3.org/TR/xslt20/#unprefixed-qnames
Interessant dat XSLT2, zijn er al processors/transformers die dat ondersteunen?
Pagina: 1