2011-08-05 59 views
5

Tôi đang làm rất nhiều XPath với trình duyệt "thông thường & hiện đại" (FF, Chrome, Opera, Safari ...) nhưng tôi đang tìm thư viện javascript cho phép IE hỗ trợ phương thức document.evaluate().Có thư viện JS để cung cấp khả năng xpath cho IE

Hiện nó có tồn tại không? Tôi biết có một số câu hỏi tương tự trong StackOverflow, nhưng họ đã được hỏi & trả lời nhiều năm trước đây.

Ý tưởng là: yếu tố mã trong đọc xpath & cũng sản xuất (cùng) xpath.


Cập nhật, 08 Tháng 8 năm 2011:

tôi tìm ra lib bởi @ExtremeCoder đây đề xuất: http://sourceforge.net/projects/html-xpath/

Đây thực sự là những gì tôi cần (nó "đè" document.evaluate chỉ cho IE) ... nhưng nó tạo lỗi trên chrome & nó không hoạt động nhiều hơn trên IE:/


Cập nhật 29 tháng 8 năm 2012 (vâng, một năm sau).

Tôi kiểm tra một loạt thư viện. Rất nhiều trong số đó ghi đè lên document.evaluate không phải là rất mạnh hoặc bị ảnh hưởng cho các lỗi khác nhau. Cuối cùng tôi sử dụng XSLT Google Ajax cũ tốt mà không có phần XSLT;)

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

(vì vậy tôi xác nhận câu trả lời của bạn @Cheeso)

Bằng cách này rất nhiều (hoặc tất cả) các thư viện không còn được duy trì nữa.


Cập nhật một lần nữa, ngày 28 tháng 9 năm 2012:

Google bắt đầu một dự án lib XPath. Tôi chưa thử nghiệm nhưng nó có vẻ đầy hứa hẹn và cập nhật. http://code.google.com/p/wicked-good-xpath/

Như thường lệ, cảm ơn Microsoft (dành cho nhà thám hiểm 8/9/10) (sic!), Hãy tìm hiểu để hỗ trợ các tiêu chuẩn cơ bản và các hành vi trình duyệt khác.

+0

Chỉ cần tò mò về việc phát triển ứng dụng web (hoặc một số ứng dụng khác) bằng XPath hoặc thử nghiệm các ứng dụng web bằng cách sử dụng trình định vị XPath trong Selenium, v.v ...? Không hoàn toàn nhận được bối cảnh từ câu hỏi ở đây. – David

+0

Đó là xây dựng một công cụ phế liệu JS/PHP trong công ty trước đây của tôi. – AlphaB

Trả lời

0

Đây là những gì tôi sử dụng:

// 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)); 

Bạn có thể sử dụng cùng mã trong tất cả các trình duyệt, mặc dù không phải là document.evaluate(), không trực tiếp.Thay vào đó bạn sử dụng nó như thế này:

 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

Tôi nghĩ rằng nên làm điều đó.

-

xin lỗi của, tôi nghĩ rằng trang web này thực sự là chính xác những gì bạn đang tìm kiếm: http://www.dashop.de/blog/en/dev/JavaScript/content/XPath/JavaScript-XPath-Implementation.html

+0

Khá cũ, phải không? Và liên kết đã chết:/ – AlphaB

+0

Xin lỗi về điều đó. Tôi đã thêm một trang web mới mà tôi bao gồm một liên kết đến một thư viện cho những gì bạn cần. Liên kết trên cái đó không chết. – ExtremeCoder

+0

Ok. Tôi sẽ kiểm tra nó. Nhưng tôi không chắc liệu tôi có thể ghi đè lên document.evaluate trong IE (có nghĩa là cùng một mã mặc định hiện tại cho tất cả trình duyệt (vâng, ước mơ đẹp)) – AlphaB

0

Đây là việc thực hiện qua trình duyệt mới nhất của XPath trong Javascript: https://github.com/andrejpavlovic/xpathjs

Nó là đầy đủ chức năng và đơn vị được kiểm tra, và đã hỗ trợ tuyệt vời. Phần thú vị nhất là nó cũng hỗ trợ không gian tên!

+0

Có vẻ tốt đẹp nhưng tôi đã thay đổi công việc một năm trước và tôi không làm công cụ xpath thường xuyên. Nếu một người dùng SO cũng có thể kiểm tra nó, tôi sẽ vui lòng cập nhật câu hỏi của tôi và xác nhận câu trả lời này. – AlphaB

Các vấn đề liên quan