[XSLT] insert parsed data?

Pagina: 1
Acties:

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Simpel probleem maar zit er al een dag mee bezig en al tientallen dingen geprobeert - en met googlen kun je op zulke subtielen toch niets vinden.

XML:
1
2
3
4
5
6
7
8
9
//externe xml-file: nodes.xml
<nodes>
  <node id="world"><content>world</content></node>
  <node id="hello_world"><content>Hello <insert id="world"/></content></node>
<nodes>
//main xml-file
<dummy>
    <base><insert id="hello_world" />!</base>
</dummy>


code:
1
2
3
4
5
6
<xsl:apply-templates select="base" />
<xsl:template match="insert">
   <xsl:variable name="danode" select="document('nodes.xml')/nodes/node[@id = current()/@id]" />
    <xsl:copy-of select="$danode/content"/>
    <xsl:apply-templates/>
</xsl:template>


nu krij ik : Hello <insert id="world" /> !
maar ik wil: Hello World !

ook met value-of lukt het niet - de data die ik erin copieert wordt niet geinterpreteert. Ik heb al met modes/param/named templates enzovoorts het proberen te oplossen steeds zonder success.

ik zou dus zoiets als <xsl:copy-and-apply select=".."/> maar zoiets bestaat zover ik me XSL boek kan zien niet...

Alle hulp is appreciated...

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
sorry voor weer een post die ik een uur nadien zelf oplos. XSLT is wel het moeilijkst om te 'vatten' dat ik al ben tegengekomen.

De oplossing was embarrasingly simpel:

ipv een <value-of> of <copy-of> or <copy> moest het gewoon een apply-templates zijn! want deze gaat gewoon lekker recusief door en copied the content zonder probs..

dus <xsl:apply-templates select="$danode/content" />

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
hobbit_be: het moest gewoon een apply-templates zijn! want deze gaat gewoon lekker recusief door en copied the content zonder probs..
Voor de duidelijkheid en meer begrip: dat komt niet zozeer door apply-templates, maar door de default templates van XSLT. Er zijn twee default templates: de ene levert gegeven een text node die text node op, de andere past gegeven een element alle templates opnieuw toe op de kinderen van die node.

Vandaar dat je dus als je apply-templates op een text node toepast, je als resultaat die text node krijgt.

Deze default templates kan je overigens gewoon herdefinieren, wat op zich soms wel duidelijkheid verschaft: ze zijn verrot handig, maar soms hebben ze ook rare effecten als je niet beseft dat ze er zijn.

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


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Hmm die was ik al tegengekomen - ben ik correct als ik denk dat het in feite een

<xsl:copy select="...?">
....
<apply />
</xsl:copy>

doet? want ik heb net gezelen in m'n addendum van O'Really XSLT dat alleen copy de geinvoerde data nog echt gaat interpreteren...

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Zie de standaard:

http://www.w3.org/TR/xslt#built-in-rule

De twee waar ik op doelde:
code:
1
2
3
4
5
6
7
<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>
 
<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

[ Voor 18% gewijzigd door mbravenboer op 02-07-2003 17:09 ]

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


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
hmm idd het is weer niet goed te vatten -

als ik bijvoorbeeld

<vars>
<var id="hello">hello</var>
<var id="doh">hello <var id="hello"/></var>
</vars>

dan lukt het niet , dan geeft ie zelfs een StackOverflow Error? Maar ik ziet niet in waarom?

die default gevallen gaan een apply doen als er kinderen zijn toch en value-of wanneer er iets staat. Maar mijn 2de var is toch een match voor * ...

enige help om dus een

<var id="doh"/> te kunnen doen zonder de content nog eens te wrappen zou leuk zijn - ik snap er steeds minder van.

code:
1
2
3
<xsl:template match="var">
      <xsl:value-of select="$var_location/var[@id = current()/@id]" />
</xsl:template>


werkt dus niet want die gaat de info niet parsen en

code:
1
2
3
<xsl:template match="var">
      <xsl:apply-templates select="$var_location/var[@id = current()/@id]" />
</xsl:template>


geeft dus een StackOverFlow...

Dan heb je de opties wel gehad. (want copy doet per definitie niets).

zelfs Perl vind ik nog leesbaarder :) (en dat voor iemand die ? : NOOIT gebruikt in C/C++ ;) )

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Sowieso is value-of gebruikt bijna altijd onnodig en vaak zelfs fout. value-of kan niet omgaan met structuur en is daardoor eigenlijk vrijwel overbodig omdat je de value-of van een text node altijd kan vervangen door een apply-templates. Die past dan immers zo'n default template toe, die als resultaat de text node oplevert.

Het voordeel van apply-templates is dan dat je het gedrag eventueel nog kan aanpassen door een specifieke template te schrijven en dat je altijd nog kan omgaan met structuur.

Ik denk dat de problemen in dit geval veroorzaakt worden doordat je voor zowel de declaratie als het gebruik van een var dezelfde constructie gebruikt. Hierdoor is het al snel mogelijk om die twee door elkaar te gaan halen.

Het is veel duidelijk om hier onderscheid in te gaan maken:

code:
1
2
3
4
<vars>
  <var id="hello">hello</var>
  <var id="doh">hello <var ref="hello"/></var>
</vars>

Bij een declaratie gebruik je dus id, bij de verwijzing gebruik je bijvoorbeeld ref. Als je nu naar een var met een id attribuut verwijst in een XPath expressie, weet je altijd dat je een declaratie te pakken hebt. Dit zorgt voor duidelijkheid :) .

Het verschil tussen variabele declaratie en variabele gebruik hangt nu dus niet meer af van de context waarin het var element voorkomt.

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


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
mbravenboer benoem ik hiermee tot XSLT-GOD (wat ik al wist) _/-\o_ * Pi.

nu snap ik het weer: door een apply-templates los te laten op een node die
<var id=""/> (declaratie had) en wat dus wordt teruggeven door de select gaat ie zichzelf
aanroepen enzovoorts.

jammer dat ik nu ref's gaan gebruiken maar zoals U als zei: tis overzichtelijker (ik wou het niet doen omdat ik graag de id link onduidelijk hou omdat het niet altijd een ref moet zijn) het gaat vast ook met een mode - ie: calling and interpret ofzo. Maar je hebt vast nog redenen voor ref.

alsnog de oplossing.

code:
1
2
3
4
5
6
7
8
9
10
  <xsl:template match="var">
     <xsl:choose>
       <xsl:when test="@ref"> <!-- calling mode -->
           <xsl:apply-templates select="$var_location/var[@id = current()/@ref]" />
       </xsl:when>
       <xsl:otherwise> <!-- dec mode -->
           <xsl:apply-templates />
       </xsl:otherwise>
     </xsl:choose>
  </xsl:template>


alsnog hopen bedankt! (ben nog aan het nadenken of ik nu toch met id's blijf of met ref ;) - tja ik ben een koppige ;))

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
hobbit_be: mbravenboer benoem ik hiermee tot XSLT-GOD
Hehe ;) en dat terwijl ik het eigenlijk zelden of nooit meer gebruik.... Kennelijk heb ik het ooit toch wel aardig goed geleerd ;) .

Het merkwaardig van XSLT is dat mensen vaak in de val trappen dat het zo makkelijk lijkt: XPath ziet er wel logisch uit en verder is het ook allemaal wel vrij overzichtelijk omdat er maar weinig contructies zijn. Om het echt goed toe te passen heb je echter toch wel aardig wat inzicht nodig over de manier waarop XSLT werkt: wat is de precieze betekenis van constructies? Ik geloof dat je die nu aardig door begint te krijgen :) .

Af en toe heb ik weleens het idee dat die default templates meer kwaad dan goed doen ...

Dit is trouwens misschien nog mooier:
code:
1
2
3
4
5
6
7
  <xsl:template match="var[@ref]">
    <xsl:apply-templates select="$var_location/var[@id = current()/@ref]" />
  </xsl:template>
 
  <xsl:template match="var[@id]">
    <xsl:apply-templates />
  </xsl:template>

Zo houd je de beide gevallen mooi gescheiden en hoef je minder onderscheid te maken. Liefst doe je dat gelijk in de match voorwaarde van een template.
ben nog aan het nadenken of ik nu toch met id's blijf of met ref ;) - tja ik ben een koppige ;)
Hehe ;) . Het interessante is dat zulke keuzen ook spelen in het ontwerpen van abstract syntaxen voor programmeertalen (wat jouw taal in feite ook bijna is). Het is een kwestie van smaak wat je dan verkiest, maar ik vind een verschillende naamgeving zeer verduidelijkend.

[ Voor 8% gewijzigd door mbravenboer op 03-07-2003 17:59 ]

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


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
mbravenboer schreef op 03 juli 2003 @ 17:57:
Ik geloof dat je die nu aardig door begint te krijgen :) .
yep gaat al een heel pak vlotter - heb nu zelfs al een hele output. Een vriend vond het gek dat ik die var/link allemaal zo afzonderlijk wou zetten - maar dit lijkt me net het voordeel van XSLT+XML = geen dubbel gedoe en eindelijk de mogelijkheid om redundancy tot 0 te verdringen. zo wil ik maar op 1 plek bijvoorbeeld www.tweaker.net url definieren. snapt ie niet :) (mijn personal waarvoor dit moet is nu zo'n 120 pages en das allemaal copy/paste ;).)
Dit is trouwens misschien nog mooier:

...

Zo houd je de beide gevallen mooi gescheiden en hoef je minder onderscheid te maken. Liefst doe je dat gelijk in de match voorwaarde van een template.
idd - dat is nu weer een optie - kan je helaas geen geld geven voor al je tips - hopelijk ben ik op het einde van dit 'avontuur' op jouw niveau.

Als je ooit wil weten hoe je goede Moussaka wil maken kan ik je WEL helpen ;). Op IT vast niet.
Pagina: 1