2011-08-05 26 views
5

Estoy haciendo un montón de XPath con el navegador "normal & moderno" (FF, Chrome, Opera, Safari ...) pero estoy buscando una biblioteca javascript que permite que IE admita el método document.evaluate().¿Hay una biblioteca JS para proporcionar capacidades xpath a IE

¿Existe? Sé que hay algunas preguntas similares en StackOverflow, pero se les preguntó & respondidas hace muchos años.

La idea es: factorizar el código en la lectura de xpath & también produciendo (mismo) xpath.


actualización, 8 de agosto de 2011:

encuentro la lib propuesto por @ExtremeCoder aquí: http://sourceforge.net/projects/html-xpath/

Esto es realmente lo que necesito (que document.evaluate "anular" sólo para IE) ... pero crea fallo en el cromo & no funciona más en IE:/


Actualización 29 de agosto de 2012 (sí, un año después).

Pruebo una amplia gama de biblioteca. Muchos de los que anulan el documento. Evalúan no son muy fuertes o sufren por diferentes errores. finalmente se utilizo el buen viejo XSLT Google Ajax sin la parte XSLT;)

http://goog-ajaxslt.sourceforge.net/

(así que validar su respuesta @Cheeso)

Por cierto muchas (o todas) estas bibliotecas ya no se mantienen.


actualización de nuevo, 28 de septiembre de 2012:

Google comienza otro proyecto lib XPath. No lo pruebo todavía, pero parece prometedor y actualizado. http://code.google.com/p/wicked-good-xpath/

Como de costumbre, gracias a Microsoft (for explorer 8/9/10) (sic!), Aprenda a soportar estándares básicos y otros comportamientos de navegadores.

+0

Simplemente curioso es esto con respecto al desarrollo de aplicaciones web (u otras aplicaciones) usando XPath o probando aplicaciones web usando localizadores XPath en Selenium, etc. No entiendo el contexto de la pregunta aquí. – David

+0

Fue para construir una herramienta de chatarra JS/PHP en mi empresa anterior. – AlphaB

Respuesta

0

Esto es lo que yo uso:

// xpath.js 
// ------------------------------------------------------------------ 
// 
// a cross-browser xpath class. 
// Derived form code at http://jmvidal.cse.sc.edu/talks/javascriptxml/xpathexample.html. 
// 
// Tested in Chrome, IE9, and FF6.0.2 
// 
// Author  : Dino 
// Created : Sun Sep 18 18:39:58 2011 
// Last-saved : <2011-September-19 15:07:20> 
// 
// ------------------------------------------------------------------ 

/*jshint browser:true */ 

(function(globalScope) { 
    'use strict'; 

    /** 
    * The first argument to this constructor is the text of the XPath expression. 
    * 
    * If the expression uses any XML namespaces, the second argument must 
    * be a JavaScript object that maps namespace prefixes to the URLs that define 
    * those namespaces. The properties of this object are taken as prefixes, and 
    * the values associated to those properties are the URLs. 
    * 
    * There's no way to specify a non-null default XML namespace. You need to use 
    * prefixes in order to reference a non-null namespace in a query. 
    * 
    */ 

    var expr = function(xpathText, namespaces) { 
     var prefix; 
     this.xpathText = xpathText; // Save the text of the expression 
     this.namespaces = namespaces || null; // And the namespace mapping 

     if (document.createExpression) { 
      this.xpathExpr = true; 
      // I tried using a compiled xpath expression, it worked on Chrome, 
      // but it did not work on FF6.0.2. Threw various exceptions. 
      // So I punt on "compiling" the xpath and just evaluate it. 
      // 
      // This flag serves only to store the result of the check. 
      // 

       // document.createExpression(xpathText, 
       // // This function is passed a 
       // // namespace prefix and returns the URL. 
       // function(prefix) { 
       //  return namespaces[prefix]; 
       // }); 
     } 
     else { 
      // assume IE and convert the namespaces object into the 
      // textual form that IE requires. 
      this.namespaceString = ""; 
      if (namespaces !== null) { 
       for(prefix in namespaces) { 
        // Add a space if there is already something there 
        if (this.namespaceString.length>1) this.namespaceString += ' '; 
        // And add the namespace 
        this.namespaceString += 'xmlns:' + prefix + '="' + 
         namespaces[prefix] + '"'; 
       } 
      } 
     } 
    }; 

    /** 
    * This is the getNodes() method of XPath.Expression. It evaluates the 
    * XPath expression in the specified context. The context argument should 
    * be a Document or Element object. The return value is an array 
    * or array-like object containing the nodes that match the expression. 
    */ 
    expr.prototype.getNodes = function(xmlDomCtx) { 
     var self = this, a, i, 
      doc = xmlDomCtx.ownerDocument; 

     // If the context doesn't have ownerDocument, it is the Document 
     if (doc === null) doc = xmlDomCtx; 

     if (this.xpathExpr) { 
      // could not get a compiled XPathExpression to work in FF6 
      // var result = this.xpathExpr.evaluate(xmlDomCtx, 
      //  // This is the result type we want 
      //  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, 
      //  null); 

      var result = doc.evaluate(this.xpathText, 
       xmlDomCtx, 
       function(prefix) { 
        return self.namespaces[prefix]; 
       }, 
       XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, 
       null); 

      // Copy the results into an array. 
      a = []; 
      for(i = 0; i < result.snapshotLength; i++) { 
       a.push(result.snapshotItem(i)); 
      } 
      return a; 
     } 
     else { 
      // evaluate the expression using the IE API. 
      try { 
       // This is IE-specific magic to specify prefix-to-URL mapping 
       doc.setProperty("SelectionLanguage", "XPath"); 
       doc.setProperty("SelectionNamespaces", this.namespaceString); 

       // In IE, the context must be an Element not a Document, 
       // so if context is a document, use documentElement instead 
       if (xmlDomCtx === doc) xmlDomCtx = doc.documentElement; 
       // Now use the IE method selectNodes() to evaluate the expression 
       return xmlDomCtx.selectNodes(this.xpathText); 
      } 
      catch(e2) { 
       throw "XPath is not supported by this browser."; 
      } 
     } 
    }; 


    /** 
    * This is the getNode() method of XPath.Expression. It evaluates the 
    * XPath expression in the specified context and returns a single matching 
    * node (or null if no node matches). If more than one node matches, 
    * this method returns the first one in the document. 
    * The implementation differs from getNodes() only in the return type. 
    */ 
    expr.prototype.getNode = function(xmlDomCtx) { 
     var self = this, 
       doc = xmlDomCtx.ownerDocument; 
     if (doc === null) doc = xmlDomCtx; 
     if (this.xpathExpr) { 

      // could not get compiled "XPathExpression" to work in FF4 
      // var result = 
      //  this.xpathExpr.evaluate(xmlDomCtx, 
      //  // We just want the first match 
      //  XPathResult.FIRST_ORDERED_NODE_TYPE, 
      //  null); 

      var result = doc.evaluate(this.xpathText, 
       xmlDomCtx, 
       function(prefix) { 
        return self.namespaces[prefix]; 
       }, 
       XPathResult.FIRST_ORDERED_NODE_TYPE, 
       null); 
      return result.singleNodeValue; 
     } 
     else { 
      try { 
       doc.setProperty("SelectionLanguage", "XPath"); 
       doc.setProperty("SelectionNamespaces", this.namespaceString); 
       if (xmlDomCtx == doc) xmlDomCtx = doc.documentElement; 
       return xmlDomCtx.selectSingleNode(this.xpathText); 
      } 
      catch(e) { 
       throw "XPath is not supported by this browser."; 
      } 
     } 
    }; 


    var getNodes = function(context, xpathExpr, namespaces) { 
     return (new globalScope.XPath.Expression(xpathExpr, namespaces)).getNodes(context); 
    }; 

    var getNode = function(context, xpathExpr, namespaces) { 
     return (new globalScope.XPath.Expression(xpathExpr, namespaces)).getNode(context); 
    }; 


    /** 
    * XPath is a global object, containing three members. The 
    * Expression member is a class modelling an Xpath expression. Use 
    * it like this: 
    * 
    * var xpath1 = new XPath.Expression("/kml/Document/Folder"); 
    * var nodeList = xpath1.getNodes(xmldoc); 
    * 
    * var xpath2 = new XPath.Expression("/a:kml/a:Document", 
    *         { a : 'http://www.opengis.net/kml/2.2' }); 
    * var node = xpath2.getNode(xmldoc); 
    * 
    * The getNodes() and getNode() methods are just utility methods for 
    * one-time use. Example: 
    * 
    * var oneNode = XPath.getNode(xmldoc, '/root/favorites'); 
    * 
    * var nodeList = XPath.getNodes(xmldoc, '/x:derp/x:twap', { x: 'urn:0190djksj-xx'}); 
    * 
    */ 

    // place XPath into the global scope. 
    globalScope.XPath = { 
     Expression : expr, 
     getNodes : getNodes, 
     getNode : getNode 
    }; 

}(this)); 

Usted puede utilizar el mismo código en todos los navegadores, aunque no es document.evaluate(), no directamente.En su lugar se utiliza de esta manera:

 var xpath = new XPath.Expression("/a:kml/a:Document", 
             { a : 'http://www.opengis.net/kml/2.2' }); 
     var node = xpath.getNode(xmldoc); 
1

http://blogs.msdn.com/b/dareobasanjo/archive/2004/04/20/116815.aspx

creo que debería hacerlo.

-

appologies, creo que este sitio es en realidad exactamente lo que está buscando: http://www.dashop.de/blog/en/dev/JavaScript/content/XPath/JavaScript-XPath-Implementation.html

+0

Bastante viejo, ¿no? Y el enlace está muerto:/ – AlphaB

+0

Lo siento. He agregado un nuevo sitio web que incluye un enlace a una biblioteca para lo que necesita. El enlace de ese no está muerto. – ExtremeCoder

+0

Ok. Lo probaré. Pero no estoy seguro de si puedo anular el documento. Evaluar en IE. (Que significa el mismo código predeterminado actual para todos los navegadores (sí, buen sueño)) – AlphaB

0

aquí es la más reciente aplicación multi-navegador de XPath en Javascript: https://github.com/andrejpavlovic/xpathjs

Es completamente funcional y unidad probada, y tiene un gran apoyo. La mejor parte es que también admite espacios de nombres.

+0

Me parece bien pero cambié de trabajo hace un año y no hago cosas de xpath regularmente. Si un usuario SO también puede probarlo, me gustaría actualizar mi pregunta y validar esta respuesta. – AlphaB

Cuestiones relacionadas