Newsgroup: it.comp.lang.javascript
Titolo: XPath, XMLHttpRequest e parsing DOM

Salve,
Vorrei sottoporvi un problema che è sorto mentre giocherellavo con
javascript e XPath.
Ho un oggetto r di tipo XMLHttpRequest; faccio una richiesta verso una
pagina dentro il mio dominio, tutto ok. Ricevo i soliti responseText e
responseXML; il responseXML con pagine diverse a volte è null, quindi
probabilmente il codice non è valido. Poco male, uso un oggetto
    DOMParser().parseFromString(r.responseText, "text/xml")
per crearmi il documento DOM.
Una volta ottenuto l'oggetto (diciamo sia x), provo a fare
    x.evaluate(query, x, null, 0, null)
dove query è una espressione XPath valida. Ecco il problema: se creo
una query del tipo "//*[@id='qualcosa']" oppure "//*" il tutto
funziona (nel primo caso mi restituisce gli elementi che hanno come id
'qualcosa' e nel secondo mi restituisce tutti gli elementi). Se faccio
una query del tipo "/html/body" oppure "/ol/li/a" oppure qualsiasi
altra cosa che non usi il wildcard *, la query mi restituisce sempre
null. La query non è sbagliata poiché, provando l'evaluate nella
pagina reale (ovvero non tramite la richiesta ma tramite la console
javascript) il tutto funziona.
In poche parole, viene validata solo la query "//*"; le altre
(esempio: "//*/li" no, anche se errata).
Avete per caso idea di cosa possa essere? Vi giuro, non riesco a
capire! Credo sia un problema del documento in se preso dalla
richiesta ma non conosco e non riesco a trovare altro modo di parsare
il responseText in DOM (non posso far affidamento su responseXML).
Vi ringrazio, in ogni caso!

 il responseText in DOM (non posso far affidamento su responseXML).
Onestamente così non mi vengono consigli da darti se non il più 
classico: hai ricreato fuori dal tuo programma un codice di esempio che 
riproduca il problema?
Fallo e al novanta per cento ti accorgerai di cosa c'è che non va, 
altrimenti visto che l'hai in mano proponilo anche a noi che altrimenti 
si va alla cieca.

 si va alla cieca.
Ciao! Grazie per la risposta!
Allora, il responseXML è null probabilmente perché l'oggetto viene
servito con un content sbagliato, proverò a forzarlo in text/xml o
text/html.
Il documento, purtroppo, è valido (nel metodo in cui lo parso), poiché
il dom del Document creato non contiene parsererror.
Riguardo il problema XPath sì, ho ricreato il tutto in un altro
ambiente, stesso codice etc... e purtroppo non funziona uguale; come
sopra però, se uso una shell e faccio la query tramite l'oggetto
Document (ovvero la pagina su cui voglio lanciare la query è il
Document stesso) allora funziona.
Il codice della pagina è questo: 
http://pastebin.com/njtdvcLH
Il codice di prova è questo: 
http://pastebin.com/QdXzhDba

 Il codice di prova è questo: 
http://pastebin.com/QdXzhDba
Ok, mi è diventato tutto chiaro vedendo il codice e, sì, potevo 
arrivarci anche prima.
Il tuo problema è la risoluzione del namespace xhtml: infatti le query 
"generiche" ti funzionavano, quelle specifiche con elementi no.
Soluzione uno, lo dico a scopo "didattico" ma non va applicata nel tuo 
caso: togli la dichiarazione del namespace dal codice xhtml e tutto 
andrà magicamente a posto.
Soluzione reale: devi scriverti un namespace resolver personalizzato e 
passare quello al metodo evaluate, dopodiché fare le query col prefisso 
da te indicato.
Ovvero:
function nsResolver(prefix){
     var resolvers = {
         "xhtml": "
http://www.w3.org/1999/xhtml
",
         "rdf": "
http://www.w3.org/1999/02/22-rdf-syntax-ns#
",
         "xsl": "
http://www.w3.org/1999/XSL/Transform
"
         // e tutti quelli che vuoi metterci, a te serve solo il primo
     };
     return resolvers[prefix] || null;
}
var xpe = new XPathEvaluator();
var result = xpe.evaluate("//xhtml:div/xhtml:ol",
                           aXmlDoc.documentElement, nsResolver,
                           XPathResult.ANY_TYPE, null);
Se non mi fossi spiegato bene, facci sapere.


wrote:

Ti sei spiegato benissimo! E infatti questa mattina leggevo le
specifiche di XPath e mi son imbattuto nella definizione di ns ed ero
quasi arrivato ad una soluzione del genere! Ma il tuo codice funziona
benissimo! Più che altro adesso devo trovare un modo per prendermi il
namespace corrispondente alla pagina. Non ho controllato se posso
farlo tramite DOM ma, per risolvere tutte le evenutalità che
potrebbero sorgere, sto pensando di parsare il doctype con qualche
regexp e capire che tipo di namespace devo usare. In ogni caso, grazie.

 regexp e capire che tipo di namespace devo usare. In ogni caso, grazie.
Puoi recuperare l'URI del namespace, ma sicuro che ti serva?
Poi le query che fai sono specifiche su certi elementi quindi dovresti 
saperlo a priori senza ricavarlo dinamicamente.
Magari non sto ricostruendo bene la tua situazione, ma dovesse servirti:
http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI
In casi particolari potrebbe servirti anche questo:
https://developer.mozilla.org/En/Code_snippets/LookupNamespaceURI


wrote:

Purtroppo non lo so a priori perché non so che tipo di documento abbia
tra le mani; infatti "forzo" il MIME type a text/xml e il content-type
nella richiesta sempre a text/xml. Il problema è che non so se per
ogni documento usare il prefisso "xhtml" vada bene; più che altro ho
notato che nell'elemento html nel DOM gli attributi hanno un elemento
xmlns che contiene l'uri del namespace: potrei sfruttare quello?
Usando lookupNamespaceURI prendo sempre e solo null (e gli attributi
prefix e namespaceURI nel DOM sono null).

 prefix e namespaceURI nel DOM sono null).
Mettiamo sempre che "aXmlDoc" sia il tuo documento:
var nsURI = aXmlDoc.documentElement.lookupNamespaceURI("");
nsURI dovrebbe avere "
http://www.w3.org/1999/xhtml
" come valore.

 nsURI dovrebbe avere "
http://www.w3.org/1999/xhtml
" come valore.
Sì, intedevo questo! Solo che nel campo namespareURI dell'oggetto
(intendo nel DOM) mi compariva null.
Facevo query specifiche perché in quell'esempio sapevo di poter fare
quel tipo di query; infatti nella richiesta "forzo" a leggere il
response come un tipo text/xml, così da poter usare il responseXML,
invece di prendere il responseText e parsarlo tramite il DOMParser.
Mi interrogavo sul fatto di capire quale namespace usare poiché, per
esempio, potrei leggere un documento x e non un documento xhtml,
quindi dovrei indicare quale namespace usare per quel documento. Non
faccio delle query "specifiche" poiché le costruisco a partire dal
documento (quelle nel primo esempio erano solo delle prove ad-hoc!).
In ogni caso, grazie mille!

 In ogni caso, grazie mille!
Di niente, siam qui apposta. Se hai dubbi fai pure un fischio.