IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AJAX Discussion :

[AJAX] DOMParser et parseFromString avec Firefox 3


Sujet :

AJAX

  1. #1
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Décembre 2007
    Messages : 17
    Par défaut [AJAX] DOMParser et parseFromString avec Firefox 3
    Bonjour,

    Je dois convertir une application web ie seulement pour qu'elle supporte firefox 3.

    Dans l'application, un objet XMLHttpRequest retourne une string construite côté PHP. Jusque là, aucun problème, le XML dans la string est intact. Par contre, pour construire la page, lancer les évenements, etc. des XPaths doivent être utilisés pour extraire l'information. Nous transformons donc la string en XML à l'aide de la méthode parseFromString de DOMParser.

    Le problème, c'est que cette méthode transforme les noeuds xml vide de type
    en
    Donc, quand les parties voulues du xml sont ajoutés à la page html par innerHTML ou par node.appendChild, Firefox 3 n'interprète pas bien les balises de type <item id=... /> dans les ilots de données xml et interprète ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <item ... />
    <item ... />
    <item ... />
    comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <item ...>
      <item ...>
        <item ...></item>
      </item>
    </item>
    en considérant les premières balises comme n'étant pas fermées.

    Le doctype utilisé est XHTML 1.0 transitionnel avec un mimetype text/html. Utiliser le mimetype application/xhtml+xml est inpensable puisqu'à ce point, rendre l'application "réellement compatible" xhtml ne pourrait être fait dans des délais raisonnables.

    De plus, les "data island" sont essentiels dans le code puisque nous utilisons des composants ajax qui s'initialisent à partir de ces ilots de données xml (Le grid et le combo de nitobi).

    Est-ce que quelqu'un d'entre vous connaîtrais une méthode pour contourner ce problème?

  2. #2
    Membre Expert Avatar de DoubleU
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 106
    Par défaut
    Salut,

    Dans l'application, un objet XMLHttpRequest retourne une string construite côté PHP. Jusque là, aucun problème, le XML dans la string est intact. Par contre, pour construire la page, lancer les évenements, etc. des XPaths doivent être utilisés pour extraire l'information. Nous transformons donc la string en XML à l'aide de la méthode parseFromString de DOMParser.
    Pourquoi utiliser DOMParser et pas simplement responseXML ?

    Donc, quand les parties voulues du xml sont ajoutés à la page html par innerHTML ou par node.appendChild,
    Est-ce que tu pourrais donner le code de la partie correspondante, car j'ai un doute sur la compréhension de ce que vous faites. Vous n'essayez pas d'ajouter directement les parties provenant du XML au DOM de la page? Car les 2 api, même si elles possèdent des méthodes de même signature, sont différentes.

  3. #3
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Décembre 2007
    Messages : 17
    Par défaut
    Pourquoi utiliser DOMParser et pas simplement responseXML ?
    Parce que ce qui est créé côté serveur est créé à l'aide de template php et est retourné sous forme de string. responseText est défini (et contient, sous forme de string, le xml sous la forme voulue), mais responseXML est null.

    Est-ce que tu pourrais donner le code de la partie correspondante, car j'ai un doute sur la compréhension de ce que vous faites. Vous n'essayez pas d'ajouter directement les parties provenant du XML au DOM de la page? Car les 2 api, même si elles possèdent des méthodes de même signature, sont différentes.
    Lorsqu'on reçoit l'objet XmlHttpRequest, on fait ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    sMsg = poXmlHttpRequest.responseText;
    objDom = createXMLObjectFromString(sMsg);
    Le problème débute ici, lorsque createXMLObjectFromString change les <...></...> en <.../>.
    createXMLObjectFromString est, pour firefox:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    function createXMLObjectFromString(pstrXML)
    {
        //Remove useless whitespaces, carriage returns and line feeds around the xml document. 
        var strCleanedXml = pstrXML.replace(/^[\s\r\n]*/g,"").replace(/[\s\n\r]*$/g,"");
        objDomParser = new DOMParser();
        objXmlReturn = objDomParser.parseFromString(strCleanedXml, "text/xml");
        return objXmlReturn;
    }
    on passe ensuite objDom en paramètre à cette fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    function clearWindowDefsTimeout(pobjDom)
    {
        var oWins;
        var oControl;
     
        oWins = xmlSelectNodes(pobjDom,"//window-def");
     
        //
        var strHTMLDivRelation = "";
        for(var i=0; i < oWins.length; i+=1)
        {
            sWindId = "";
            sWindId = oWins[i].getAttribute("id");
     
            oNodeCtn = xmlSelectSingleNode(oWins[i],"./contenu");
     
            oControl = document.getElementById(sWindId);
            if(oControl !== null)
            {    
                //This validation is used for by-passe the display.
                //add attribute show=false on element to manualy display it
                if(!oControl.show)
                {
                    if(oControl.style.display === "none")
                    {
                       oControl.style.display = "block";
                    }
                }
                oControl.innerHTML = "";
                purge(oControl);
                //Clean up the IE garbage collector before reassign it a new value
                oControl.innerHTML = getXML(oNodeCtn);
            }
            else if(document.getElementById(sWindId + "_content") !== null)
            {    
                oNodeContent = xmlSelectSingleNode(oWins[i],"./contenu/div[@id='"+ sWindId + "_content']");
                document.getElementById(sWindId + "_content").innerHTML = "";
                purge(document.getElementById(sWindId + "_content"));
                document.getElementById(sWindId + "_content").innerHTML = getXML(oNodeContent);
            }
            else
            {  
                strHTMLDivRelation = strHTMLDivRelation + getXML(oNodeCtn);
                //oDiv = createWindow(sWindId);
                //oDiv.innerHTML = "";
                //oDiv.innerHTML = getXML(oNodeCtn);
     
                //oControlRelation = document.getElementById("div_relation");
               //oControlRelation.appendChild(oDiv);
            }
     
            //oWin = null;
            //delete oWin;
        }
     
        if(strHTMLDivRelation !== "")
        {
           if(document.getElementById("div_relation") !== null)
           {
                document.getElementById("div_relation").style.display = "block";
     
                purge(document.getElementById("div_relation"));
                document.getElementById("div_relation").innerHTML = strHTMLDivRelation;
           }
        }
     
        goXMLContext = xmlSelectSingleNode(pobjDom,"//context");
     
        var oNodeAction;
        oNodeAction = xmlSelectNodes(pobjDom,"//action/rule");
        objNodeOutPut = xmlSelectNodes(pobjDom,"//action/rule[@id='send_forward_action']");
     
        if(objNodeOutPut.length == 0 && gbolSpash == true)
        {
             var objDivSplash = document.getElementById("div_splash");
             if( objDivSplash != null)
             {
                objDivSplash.style.display = "none";
                gbolSpash = false;
             }
        }
     
     
     
        //launchScript(pobjDom);
        waitResponse(false);
     
        doWindowActions(oNodeAction);
     
        addDynamicJavascript(pobjDom);
     
        pobjDom = null;
        delete pobjDom;
    }
    qui ajoute du code html et xml à la page. xmlSelectNodes et xmlSelectSingleNodes sont des fonctions qui créent un XPathEvaluator appellent evaluate avec les paramètres appropriés sous firefox. Lorsque les ajouts de xml et de html sont terminés, on ajoute les scripts avec ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
     
    function addDynamicJavascript(poXMLResponse)
    {   
        // 
        oNodesScript = xmlSelectNodes(poXMLResponse,"//script");
     
        if(oNodesScript !== null)
        {
            var sScript = "";
            oHead = document.getElementsByTagName("head")[0];
     
            //for (var oNode = oNodesScript.nextNode(); oNode; oNode = oNodesScript.nextNode())
            for(var y=0; y < oNodesScript.length; y++)
            {   
                var sSrc = oNodesScript[y].getAttribute("src");
                if(sSrc !== null && sSrc !== "")
                {
                    //TODO: Test if src has already been added ( it does not seem to cause problems if the js include already exists with ie7)
                    oScript = document.getElementsByTagName("script");
                    bFound = false;
                    for(var i=0; i< oScript.length; i++)
                    {
                      if(oScript[i].getAttribute("src") !=="")
                      {
                          if(oScript[i].getAttribute("src") == sSrc )
                          {
                            bFound = true;
                            i= oScript.length;
                          }
                      }
                    }
                    if(bFound == false)
                    {
                        var scriptTag = document.createElement("script");
                        scriptTag.setAttribute("src", sSrc);
                        scriptTag.setAttribute("type", "text/javascript");
                        oHead.appendChild(scriptTag);
                    }
                }
                else
                {
    //Todo: s'il n'y a pas d'attribut src au script, le nouveau tag script est toujours ajouté en plus de l'ancien
                    //var sDivId = oNode.getAttribute("divId");
                    var sDivId = oNodesScript[y].getAttribute("divId");
                    if(sDivId !== null && sDivId !== "")
                    {
                        var oDiv = null;
     
                        if(document.getElementById(sDivId) !== null)
                        {
                           oDiv = document.getElementById(sDivId);
                        }
                        else if(document.getElementById(sDivId + "_content") !== null)
                        {
                           oDiv = document.getElementById(sDivId + "_content");
                        }
     
                        if(oDiv !== null)
                        {
                            oScript = document.createElement("script");
                            oScript.setAttribute("type", "text/javascript");
                            //oDiv = document.getElementById(sDivId);
                            //if(oNode.firstChild !== null)
                            if(oNodesScript[y].firstChild !== null)
                            {  
                                oScript.textContent = oNodesScript[y].firstChild.nodeValue;
                            }
                            else
                            {
                                oScript.textContent = "";
                            }   
     
                            if(oScript.textContent !== "")
                            {    
                                //oScript.textContent = "try{" + oScript.textContent + "}catch(err){debugger;err=err;alert(err);}";
                            }    
                            oDiv.appendChild(oScript);
                        }
                        else
                        {
                            if(oNodesScript[y].firstChild !== null)
                            {
                                sScript += oNodesScript[y].firstChild.nodeValue;
                            }
                            //sScript += oNodesScript[i].firstChild.nodeValue;
                            //sScript += oNodesScript[y].childNodes[1].nodeValue;
                        }
                    }
                    else
                    {
                        if(oNodesScript[y].firstChild !== null)
                        {
                            sScript += oNodesScript[y].firstChild.nodeValue;
                        }
                    }
                }
     
                if(sScript !== "")
                {
                    oHeadScript = document.createElement("script");
                    oHeadScript.setAttribute("type", "text/javascript");
                    oHeadScript.textContent = sScript;
                    oHead.appendChild(oHeadScript);
                }
            }
        }
        // End
    }
    qui ajoute les scripts à exécuter pour initialiser les nouveaux composants nitobi, ajouter des validations, etc.

    Et non, on n'ajoute pas directement les parties provenant du XML au DOM de la page. Soit on les ajoute par string avec innerHTML, soit on crée, pour l'ajout des scripts, un nouvel élément où on copie la string du script dans le textContent.

  4. #4
    Rédacteur/Modérateur
    Avatar de andry.aime
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    8 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Ile Maurice

    Informations forums :
    Inscription : Septembre 2007
    Messages : 8 391
    Par défaut
    Salut,
    Je pense que cette discussion pourra t'aider un peu.

  5. #5
    Membre Expert Avatar de DoubleU
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 106
    Par défaut
    Parce que ce qui est créé côté serveur est créé à l'aide de template php et est retourné sous forme de string. responseText est défini (et contient, sous forme de string, le xml sous la forme voulue), mais responseXML est null.
    Quand tu utilises XmlHttpRequest, toutes les données, quelque soit le sens de l'échange, passent en texte, non en xml. Donc peu importe que coté php tu génères ton xml via une api dédiée ou en concaténant des chaines de caractère, quand tu récupères la réponse en javascript tu dois avoir le même résultat.
    Ce qui est étonnant, c'est que ton xhr.responseXML ne donne rien. Tu as bien ajouté le header text/xml coté php?

    Que fait la fonction getXML que tu utilises partout pour faire l'ajout via innerHTML ?

  6. #6
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Décembre 2007
    Messages : 17
    Par défaut
    En fait, c'est ce que j'ai (mal) expliqué. Le responseXML est nul puisque les templates fournissent un xml "sale" qui n'est pas considéré comme un objet XML par l'objet XMLHttpRequest. Je vais voir le thread qu'on m'a proposé à l'instant.

    EDIT:

    Je viens d'aller voir l'autre thread, et effectivement, le header n'étais pas mis. Par contre, lorsqu'il est mis, il y a une erreur puisque la string xml envoyée par le php est bourrée de saloperies (par exemple, il y a des espaces inutiles avant le début du document). Je crois que je vais règler mon problème en transformant les balises mal formées du côté javascript. Je vais voir ce que ça donne et je reviendrai si c'est trop lent.

  7. #7
    Membre Expert Avatar de DoubleU
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 106
    Par défaut
    Le coup du header te permetra peut etre de récupérer le xml depuis xhr.responseXML, mais ce n'est pas ca qui résoudra ton problème je pense.

    Fais voir le code de ta fonction getXML, parce que pour moi, c'est ici que ca foire.

  8. #8
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Décembre 2007
    Messages : 17
    Par défaut
    En fait, c'était mauvais bien avant le getXML. J'ai résolu à l'aide d'une expression régulière, mais ça reste un fix pas idéal.

    Mon getXML avant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function getXML(pObjXml)
    {  
        var objSerializer = new XMLSerializer();
        var objXMLString = XML(objSerializer.serializeToString(pObjXml)).toXMLString();
     
        return objXMLString;
    }
    et maintenant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    function getXML(pObjXml)
    {
        // To change <.../> tags to <...></...> tags
        var objRegexXmlCleaner = RegExp("<[\\s\\r\\n]*([^\\s\\n\\r>]*)([^\\>]*?)/>","g");
     
        var objSerializer = new XMLSerializer();
        var objXMLString = XML(objSerializer.serializeToString(pObjXml)).toXMLString();
     
        objXMLString = objXMLString.replace(objRegexXmlCleaner,"<$1$2></$1>");
        return objXMLString;
    }
    C'est moins lent que je le craignais, malgré des xml avec des dizaines de millier de lignes. Le seul problème est que les tags contenant > dans leurs attributs ne seront pas nettoyés, mais je peux faire avec ça. Je met le topic en résolu.

    Edit: Juste pour information, le problème vient du fait que Firefox 3 ne supporte pas les balises simples fermées <.../> dans les "xml data islands".

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [JQuery] ajax avec Firefox
    Par elvan49 dans le forum jQuery
    Réponses: 2
    Dernier message: 17/12/2007, 12h21
  2. [AJAX] Impossible de lancer une requete avec firefox
    Par thomasse dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 12/10/2007, 11h21
  3. Pb footer avec FireFox et Ajax
    Par coil1 dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 17/04/2007, 16h58
  4. [AJAX] Remplissage d'un div avec Firefox
    Par arouze dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 25/01/2007, 12h28
  5. [AJAX] Affichage avec Firefox
    Par sarapis dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 19/05/2006, 16h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo