tutorial - Implementación de XPath entre navegadores en JavaScript
xpath javascript tutorial (12)
Estoy buscando una biblioteca XPath para consultar documentos XML en FF, IE, Opera y Safari ... y no pude encontrar ninguno. ¿Has visto alguno?
Aquí está la implementación cross-browser más reciente de XPath en Javascript: https://github.com/andrejpavlovic/xpathjs
Es completamente funcional y probado en unidades, y tiene un gran soporte. La mejor parte es que también admite espacios de nombres.
Creo que puedes usar la biblioteca xpath de Cameron McCormack aquí. Funciona perfectamente para mí.
Eche un vistazo al proyecto http://dev.abiss.gr/sarissa/ . Han migrado la mayoría de las API relacionadas con XML a IE, así como también han evaluado el método en el objeto del documento. Y, de hecho, jQuery no tiene un procesador XPath, tiene un selector de ruta muy simple como: / a / b / c solamente
Es posible que desee probar el plugin jQuery XPath con compatibilidad con la sintaxis XPath 2.0 que funciona en todos los navegadores.
Esto es lo que 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));
Google acaba de lanzar Wicked Good XPath: una nueva versión del famoso JavaScript-XPath de Cybozu Lab.
Enlace: https://github.com/google/wicked-good-xpath
La versión reescrita es un 40% más pequeña y aproximadamente un 30% más rápida que la implementación original.
La otra opción podría ser LlamaLab XPath.js (aunque parece ser un poco viejo)
No creo que permita consultas ad-hoc, pero puede consultar el complemento XSLT jQuery de Johann Burkard para obtener inspiración sobre cómo implementar consultas XPath. Lo uso en mi widget jQuery Reference Dashboard y es muy sólido.
Puede hacer uso del soporte de DOM nativo existente de cada navegador. Para esto, tendrías que crear tu propio contenedor, la razón es las diferencias entre el navegador. Puede echar un vistazo a http://dotnetcaffe.blogspot.com
Atentamente
Puede usar el plugin XPath básico para jQuery para obtener la funcionalidad de consulta de XPath.
Además, podría considerar leer este artículo sobre el procesamiento XPath XML (de nuevo con jQuery)
El proyecto de código abierto AJAXSLT de Google se ajusta bien a los requisitos establecidos.
Como su propia descripción va a decir:
"AJAXSLT es una implementación de XSLT en JavaScript . Debido a que XSLT usa XPath, también es una implementación de XPath que puede usarse independientemente de XSLT . Esta implementación tiene la ventaja de que hace que XSLT esté uniformemente disponible en más navegadores que lo proporciona de manera nativa, y que se puede extender a más navegadores si es necesario. AJAXSLT es interesante para los desarrolladores que luchan agresivamente por la compatibilidad de navegador cruzado de sus aplicaciones web avanzadas ".
ACTUALIZACIÓN : a finales de 2010, Michael Kay ha estado compilando su procesador Saxon XSLT 2.0 a Javascript (por lo que está disponible para los 5 principales navegadores) utilizando GWT. Es probable que haya un sajón ligero dentro del navegador pronto.
FormFaces (implementación de XForms en JS) tiene un motor XPath confiable que se puede extraer fácilmente y usar de forma independiente.