2012-05-08 5 views
3

Je voudrais utiliser XPaths javascript dans une application web en utilisant des extensions exslt, mais je ne peux pas comprendre comment faire cela. Imaginez que je possède un document html avec quelques divs dedans. Je veux exécuter ceci:Utiliser des extensions exslt être utilisé dans javascript xpaths

namespaces={'regexp':'http://exslt.org/regular-expressions'}; 
result = document.evaluate( 
      "//div[regexp:test(.,'$')]", 
      document, 
      function(ns){ 
       return namespaces.hasOwnProperty(ns) ? namespaces[ns] : null; 
      }, 
      XPathResult.ANY_TYPE, 
      null); 

Seulement cela entraîne une exception d'expression XPath invalide dans évaluer. J'utilise le chrome.

Y a-t-il autre chose que je dois faire pour que ça marche? Je vois sur exslt.org qu'il existe des implémentations pour javascript, mais comment puis-je m'assurer qu'elles sont disponibles? Dois-je insérer mon javascript dans un élément de script namespaced dans le dom ou quelque chose de fou?

MISE À JOUR

Si cela est impossible directement à l'aide du navigateur dom + javascript et XPath, serait-il possible d'écrire XSLT en utilisant des extensions EXSLT dans le navigateur pour simuler document.evaluate (retour une liste d'éléments qui correspondent au xpath)?

+0

Avez-vous envisagé d'utiliser SaxonCE - il fournit un support pour l'exécution de XSLT 2.0 dans le navigateur (et fonctionne avec succès sur les cinq principaux navigateurs, y compris Chrome)? –

+0

s'ils exposaient un XPath20Evaluator javascript équivalent à leur XSLT20Processor qui serait génial. Malheureusement, ils n'offrent pas encore cette option. Merci pour le conseil, cependant. c'est bon de savoir que c'est là-bas. – underrun

+0

Vous n'avez pas besoin d'attendre "eux". Obtenez votre licence SaxonCE et utilisez-la. –

Répondre

1

Je ne pense pas que l'implémentation XPath du navigateur par défaut prenne en charge EXSLT. Le support javascript mentionné sur la page EXSLT est susceptible de vous permettre de fournir votre propre implémentation de la fonction exslt en utilisant in-browser.javascript. Voici one example I was able to find very quickly. Dans Firefox, par exemple, vous pouvez utiliser Saxon-B as an extension to run XSLT2.0 et Saxon-B has built-in support for exslt (unlike Saxon-HE), though you will likely be better off just using XSLT/XPath 2.0 features. Voici le regular expression syntax, par exemple. Cela dit, cependant, s'appuyer sur une extension Mozilla Saxon-B n'est pas quelque chose qui vous aidera avec Chrome ou d'autres navigateurs d'ailleurs. Cela dit, je ne pense pas que vous pouvez trouver une solution multi-navigateur pour utiliser les extensions EXSLT dans votre XPath. Le conformance section du DOM niveau 3 XPath appelle le support XPath 1.0 et ne mentionne pas EXSLT. Le INVALID_EXPRESSION_ERR est dit être jeté:

if the expression has a syntax error or otherwise is not a legal expression according to the rules of the specific XPathEvaluator or contains specialized extension functions or variables not supported by this implementation.

Enfin, voici un open bugzilla ticket pour Firefox d'ouvrir EXSLT pour leur niveau DOM 3 mise en œuvre XPath. Il semble être assis là dans un nouveau statut depuis 2007. Le billet dit que:

Currently Mozilla gives an exception "The expression is not a legal expression." even if a namespace resolver correctly resolving the EXSLT prefixes to the corresponding URLs is passed in. Voici le test case.

-

Si vous ne me dérange pas demander ce que vous vouliez exactement utiliser le regex pour? Peut-être que nous pouvons vous aider à sortir avec une combinaison de standard XPath string functions?

-

MISE À JOUR Vous pouvez construire un coureur XPath via XSLT (comme vous vous demandez dans la mise à jour à votre question) mais elle ne retourne pas les noeuds du document source, il sera Renvoie de nouveaux noeuds qui ressemblent exactement à. XSLT produit un nouveau document d'arbre de résultat et je ne pense pas qu'il existe un moyen de le laisser renvoyer des références aux nœuds d'origine. Pour autant que je sache, Mozilla (et Chrome) support XSLT non seulement pour les documents XML chargés à partir de sources externes, mais aussi pour les éléments DOM du document en cours d'affichage.

Le XSLTProcessor documentation mentionne comment tranformToFragment(), par exemple, will only produce HTML DOM objects if the owner document is itself an HTMLDocument, or if the output method of the stylesheet is HTML.

est ici d'un simple coureur XPath que je CONSTRUIT tester vos ides:

1) Tout d'abord vous auriez besoin d'un modèle XSLT pour travailler avec.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:regexp="http://exslt.org/regular-expressions" 
    extension-element-prefixes="regexp"> 

    <xsl:template match="/"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

je commencé à construire dans le JavaScript en utilisant le document.implementation.createDocument APi mais pensé qu'il serait plus facile de charger juste. FF prend toujours en charge document.load tandis que Chrome vous permet uniquement de charger des éléments à l'aide de XHR. Vous devez démarrer votre Chrome avec --allow-file-access-from-files si vous souhaitez charger des fichiers avec XHR à partir de votre disque local.

2) Une fois que nous avons le modèle chargé, nous aurions besoin de modifier la valeur de l'attribut select de l'instruction xsl:copy-of pour exécuter le XPath nous avons besoin:

function runXPath(xpath) { 
    var processor = new XSLTProcessor(); 
    var xsltns = 'http://www.w3.org/1999/XSL/Transform'; 

    var xmlhttp = new window.XMLHttpRequest(); 
    xmlhttp.open("GET", "xpathrunner.xslt", false); 
    xmlhttp.send(null); 

    var transform = xmlhttp.responseXML.documentElement; 

    var copyof = transform.getElementsByTagNameNS(xsltns, 'copy-of')[0]; 
    copyof.setAttribute('select', xpath); 

    processor.importStylesheet(transform);   

    var body = document.getElementById('body'); // I gave my <body> an id attribute 
    return processor.transformToFragment(body, document); 
} 

Vous pouvez maintenant exécuter avec quelque chose comme:

var nodes = runXPath('//div[@id]'); 
console.log(nodes.hasChildNodes()); 
if (nodes.firstChild) { 
    console.log(nodes.firstChild.localName); 
} 

il fonctionne très bien pour XPath « régulier » comme ça //div[@id] (et ne trouve pas //div[@not-there]) mais je ne peux pas le faire pour exécuter le regexp:test fonction d'extension. Avec le //div[regexp:test(string(@id), "a")] il ne se trompe pas d'erreur, retourne juste un ensemble vide.

La documentation de Mozilla suggère their XSLT processor support EXSLT. J'imagine qu'ils utilisent tous libxml/libxslt dans les coulisses de toute façon. Cela dit, je ne pouvais pas le faire fonctionner dans Mozilla non plus.

Espérons que ça aide.

Avez-vous une chance de vous en sortir avec jQuery regexp? pas susceptible d'être utile pour votre utilitaire XPath Builder mais toujours un moyen d'exécuter regexp sur les nœuds HTML.

+0

La perspective est sombre alors. Je regarde aussi seulement le chrome de soutien. Le but n'est pas de créer un xpath spécifique filtré par regex, mais de créer un créateur de xpath en html/css/javascript quelque chose comme l'extension XPath de chrome (voir https://chrome.google.com/webstore/detail/hgimnogjllphhhkhlmebbmlgjoejdpjl) . – underrun

+0

peut-être demander sur leur wiki/liste de diffusion. J'ai recherché le wiki et les problèmes pour EXSLT et j'ai trouvé celui-ci: http://code.google.com/p/chromium/issues/detail?id=111655&q=EXSLT&colspec=ID%20Pri%20Mstone%20ReleaseBlock%20Area%20Feature% 20Status% 20Propriétaire% 20Résumé. Ils doivent avoir un peu de support pour EXSLT mais je ne suis pas sûr qu'il soit exposé au DOM Level 3 XPath. Sachant que Mozilla ne l'a pas dans DOM XPath même s'ils semblent aussi l'avoir dans leur XSLT, je suppose que Chrome non plus. –

+0

@SynapticUnderrun J'ai posté une mise à jour explorant l'idée du coureur XPath basé sur XSLT. Cela fonctionne, mais pas de chance d'exécuter 'regexp:' fonctions d'extension. –

Questions connexes