Avatar billede barklund Nybegynder
24. januar 2007 - 13:30 Der er 19 kommentarer og
1 løsning

Automatisk konvertering af Objekt og XSL til DOM-struktur

Hejsa,

Jeg skal kunne have følgende to sæt inputs:

* Et objekt, der rekursivt indeholder diverse data i en simpel javascript-struktur, såsom:

{headline:"title", menu:[{text:"p1"}, {text:"p2"}, {text:"p3"}]}

* Et eksternt XLS såsom:

<?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" encoding="ISO-8859-1"/>
    <xsl:template match="/">
    <div>
        <h1><xsl:value-of select="headline"/></h1>
        <ul>
            <xsl:for-each select="menu/item">
            <xsl:sort order="ascending" select="id" />
                <li><xsl:value-of select="text"/></li>
            </xsl:for-each>
        </ul>
    </div>
    </xsl:template>
</xsl:stylesheet>

Og så få et DOM Objekt, der indeholder den tilhørende DIV, med en H4 og en UL igen med de 3 LI'er.

Jeg forestiller mig at det skal ske i 3 steps:

1) Konverter objekt til XML - den del kan jeg godt selv skrive.

2) Udfør XSLT på XML-repræsentation af objekt og XSL og få resulterende XHTML - det har de flinke mennesker hos Google vist lavet for mig her: http://goog-ajaxslt.sourceforge.net/

3) Konverter XHTML til DOM-struktur - se den del kan jeg ikke lige se, at nogen har lavet.

Er situationen korrekt vurderet, findes der nogle libraries, der kan de ønskede dele udover, hvad jeg selv har fundet, og er der eventuelt nogle alternative muligheder, som vil være meget mere oplagte at anvende?

--
Morten Barklund
Avatar billede barklund Nybegynder
24. januar 2007 - 13:31 #1
Hov, tag jer ikke af små fejl - der mangler blandt andet et id på menupunkterne, for at sorteringen vil virke, men det er en detalje - det er mere det overordnede koncept, jeg gerne vil have styr på :)
Avatar billede barklund Nybegynder
24. januar 2007 - 13:35 #2
Hm, når jeg lige kigger efter, så indeholder AJAXSLT da en DOMParser, som vidst nok opfylder step 3 - så jeg skal sådan set bare skrive den trivielle funktion til at udføre step1 - er det korrekt vurderet?
Avatar billede roenving Novice
24. januar 2007 - 20:02 #3
Hrm, jeg ville gå direkte fra json-tingen til DOM, hvadfor lave en ekstra konvertering ?-)

-- medmindre du da har ambitioner om at kunne lave mange forskellige ting (og der har jeg ikke prøvet, men json kan rimeligt direkte oversættes, da det jo i sig selv har en struktur !-)

-- men noget lignende:

var obj = eval(xmlHttpReqTxt);
var nDiv = document.createElement("div");
document.appendChild(nDiv);
var nHead = document.createElement("h1");
nDiv.appendChild(nHead);
nHead.appendChild(document.createTextNode(obj.headline));
var nUl = document.createElement("ul");
nDiv.appendChild(nUl);
var nLi;
obj.menu = obj.menu.sort(idSort);
for(i=0,im=obj.menu.length;im>i;i++){
  nLi = document.createElement("li");
  nUl.appendChild(nLi);
  nLi.appendChild(document.createTextNode(obj.menu[i].text))
}

-- og en sorteringsfunktion:

function idSort(a,b){
  return a.id > b.id ? 1 : a.id == b.id ? 0 : -1;
}

-- skrevet lige her og absolut utestet !-)
Avatar billede barklund Nybegynder
24. januar 2007 - 20:32 #4
Jamen, hvis nu jeg vil skifte mit HTML ud med en OL i stedet for en UL, A'er i hvert LI eller andet - så kan jeg rette i min XSL og voila... :)

Jeg vil aktivt bruge XSL netop til at kunne skifte repræsentation af data nemt.

Men jeg tror jeg er igennem det hele via ovenstående - og AJAXSLT er ufatteligt frækt. Det kører lynstærkt for selv komplekse strukturer og er ganske browser-kompatibelt. Og så har det jo også lige en DOMParser og en XPath implementation, som jo altid er rare at have :)

--
Morten Barklund
Avatar billede roenving Novice
24. januar 2007 - 20:46 #5
-- hvis du laver json-objekter, kan du jo angive element-type også, og via objekt-nesting sikre, at den korrekte nesting er tilstede ...

-- kort sagt, hvis du vil bruge xslt og xml-objekter, kan du lige så godt lave din xml serverside, så er json en dårlig omvej ...

-- hvis du vil bruge json, så fortsæt ad javascript-stien, da det er helt uproblematisk at lave en objekt-parser, der kan skabe et helt html-dokument (hint: ved under-objekter laves call-back !-)
Avatar billede barklund Nybegynder
24. januar 2007 - 20:58 #6
Hm, jeg ville mene at der var fjollet at sende en hel HTML-snippet genereret på serveren til klienten, når klienten istedet kan modtage et kompakt objekt og selv ud fra XSL generere HTML'en. Jeg føler også, at det giver mig bedre kontrol og mere logisk opdeling af data, repræsentation og logik.
Avatar billede roenving Novice
24. januar 2007 - 21:08 #7
-- og jeg mente bestemt ikke, at du skulle lave html og sende det, men at du skulle bruge json til at lave objekter, hvor du så også kunne lagre tag-names osv.

F.eks.

{
  {type:"h1",text:"En overskrift"},
  {type:"div",attrs:{style:{postion:"absolute",width:"380px",margin:"0 auto"},id:"minDiv",class:"divStyle"},content:{
    {type:"a",attrs:{href:"/forside.html",target:"_top"},content:"Et link"}
  }
}
Avatar billede barklund Nybegynder
25. januar 2007 - 09:22 #8
Nej, puhada... Det ville da være voldsomt grimt, at min server skulle generere alt det. Det giver da slet ingen mening, IMO. Serveren sender et objekt, klient finder en passende præsentation af det - det er en naturlig separation of concerns for mig. :)
Avatar billede olebole Juniormester
26. januar 2007 - 15:27 #9
<ole>

Ofte genereres JSON væsentligt hurtigere end XML på serveren (f.eks. er det nu en del af PHP5) - og så fylder det en hel del mindre at sende og er platformsuafhængigt.
Det er svært at få øje på fordelene ved XML fremfor JSON  ;o)

Prøv evt. at kikke på:
    http://www.json.org

/mvh
</bole>
Avatar billede barklund Nybegynder
26. januar 2007 - 16:47 #10
Jeg bruger skam JSON, men jeg vil ikke sende markup med fra serveren - serveren skal ikke bekymre sig om hvilke klasser eller repræsentationsformer klienten bruger :)
Avatar billede barklund Nybegynder
07. marts 2007 - 10:20 #11
Hm, jeg endte med helt at droppe fremgangsmåden. Kan være jeg kommer tilbage til det igen, men indtil videre vil jeg ikke bruge det.

olebole, lægger du et svar til lidt point? :)
Avatar billede olebole Juniormester
07. marts 2007 - 14:20 #12
Hej barklund ... sorry, men jeg har ikke haft tid til at være så aktiv på det seneste.
Jeg gør ofte selv det, at jeg laver en HTML-template, som jeg kloner med ELEMENT.cloneNode(true) på window.onload - og derefter fjerner fra DOM'en.
Det kan f.eks. være en tabel med en enkelt række med et vist antal celler - evt. med tilhørende span/div, etc. Alle elementer, der senere skal modtage tekst, fyldes med et '&nbsp;'.

Når du skal bruge strukturen, kan du skrive noget à la:

function insertRow(oResp) { // oResp indeholder et JSON-objekt
  // oTempl indeholder HTML-strukturen - kopieret som nævnt ovenfor
    var o = null;
    for (var i=0,j=oResp.rows.length; i<j; i++) {
        o = oTempl.cloneNode(true);
        aC = document.getElementsByTagName("td");
        aC[0].firstChild.nodeValue = oResp.rows[i].navn;
        aC[1].firstChild.nodeValue = oResp.rows[i].sex;
        aC[2].firstChild.nodeValue = oResp.rows[i].alder;
        myTableBody.appendChild(o);
    }
}

Dette er blot et helt skrabet eksempel (som ikke har noget direkte med dit problem at gøre), men med mit kendskab til dig, forventer jeg, du selv kan mulighederne i denne fremgangsmåde.
De enkelte elementer i din template kan også have CSS-klasser, du kan bruge til at identificere dem med ... men id'er skal du naturligvis passe på med (de skal jo være unikke).
Håber, du kan bruge dette til noget  ;o)
Avatar billede olebole Juniormester
07. marts 2007 - 14:23 #13
- lige lidt forklaring:
aC[0] // er en celle i tabel-rækken
aC[0].firstChild // er den tekst-node, der indeholder '&nbsp;'
aC[0].firstChild.nodeValue = "streng" // sætter værdien af tekst-noden (indholdet af cellen)
Avatar billede olebole Juniormester
07. marts 2007 - 14:25 #14
PS: Event-handlers bør ikke sættes på elementerne, før de er appended til DOM'en. Ellers oprettes i IE et temporært, lokalt script-scope for hvert uindsat element - som IE's garbage-collection ikke fjerner (= memory-leaking!)
Avatar billede barklund Nybegynder
07. marts 2007 - 16:14 #15
Absolut en smart plan. Der er bare mange templates, som i så fald skulle proppes i siden og fjernes igen. Og hvad så med ikke-javascript-browserne? Man kan selvfølgelig til dem fjerne det med CSS, but still.

Mht. handlers på ikke-tilføjede elementer, så var jeg ikke klar over det. Det vil jeg huske på (det virker dog ret irriterende at skulle holde styr på).

Se desuden mit seneste legetøj her http://exp.dk/spm/766585

:)

--
Morten Barklund
Avatar billede olebole Juniormester
07. marts 2007 - 16:33 #16
"Og hvad så med ikke-javascript-browserne" ... AJAX _er_ jo pr. definition JavaScript - så deeeeeeeeeet ..........  ;o)

Du kan jo pakke alle template-elementerne ind i et skjult div, som du fjerner i ét hug, når de er klonede ... og din template kan jo sagtens være et JS-objekt bestående af mange forskellige DOM-elementer, du har klonet.

Du skal såmænd også passe meget på, når du sætter event-handlers og/eller callback-funktioner i OOP'et JS! Her er de _virkelig_ mulighed for at opbygge en middelsvær Alzheimers i IE - med mindre man skriver sine egne dispose-metoder på objekterne ... og her dealer explicit med event-handlers  :oP
Avatar billede barklund Nybegynder
07. marts 2007 - 16:48 #17
Jaja, men det hele(!) skal jo stadig virke, til dem der ikke har javascript - graceful degradation og alt det :)

Og mht. events, så bruger jeg MochiKit.Signal så vidt muligt - den skulle rydde pænt op :)
Avatar billede olebole Juniormester
07. marts 2007 - 16:54 #18
"graceful degradation" ... nuvel - det kommer anpå, hvad det er for en app, man skriver - og hvad den skal bruges til. Til generel, offentlig webbrug: Ja  =)

Jeg er ikke så meget til færdige libraries. Jeg skriver funktionaliteten ind i min OOP-kode ... har et par base-objekter liggende, som jeg prototyper på. Så ved jeg præcist, hvad der foregår - og jeg undgår en masse unødig kode  ;o)
Avatar billede barklund Nybegynder
07. marts 2007 - 17:22 #19
Jeg har efterhånden også patchet den der mochikit så meget, at det er mit eget - jeg har i hvert fald styr på den. Og det er sgu rart og går lynhurtigt med abstraktioner til DOM, og stuff som map, partial og den slags er alt for skægt - og medvirker til hurtigere at få noget fra hånden :)
Avatar billede olebole Juniormester
09. marts 2007 - 13:18 #20
"og medvirker til hurtigere at få noget fra hånden" ... det handler mindst ligeså meget om kodevaner  ;o)

Udover, at hvergang man laver endnu en abstraktion, introducerer man samtidig endnu en fejlkilde. Én eller anden situation, der ikke er taget højde for - og som ligger og putter sig dybt nede i en kode, man ikke til hverdag forholder sig til.

Det generelle kvalitetsniveau for JS/DOM-kode i færdigstrikkede libraries på nettet afholder mig fra at bruge den slags - og skal jeg forholde mig effektivt til IE's tendens til at leak'e memory i JS-applikationer, er det ikke noget, jeg vil overlade til sådanne libs.

- men ... different strokes for different folks  ;o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester