3 Stimmen

Mit exslt Erweiterungen in Javascript xpaths verwendet werden

Ich möchte javascript XPaths in einer Web-App mit exslt Erweiterungen verwenden, aber ich kann nicht herausfinden, wie dies zu tun.

Nehmen wir an, ich habe ein Html-Dokument mit einigen Divs darin. Ich möchte dies ausführen:

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

Nur das führt zu einer Ausnahme für einen ungültigen XPath-Ausdruck in evaluate. Ich verwende Chrome.

Muss ich noch etwas anderes tun, damit das Ganze funktioniert? Ich sehe auf exslt.org, dass es Implementierungen für Javascript gibt, aber wie kann ich sicherstellen, dass diese verfügbar sind? Muss ich mein Javascript in ein namengebendes Skript-Element im Dom einfügen oder etwas Verrücktes?

UPDATE

Wenn dies nicht möglich ist, direkt mit Browser dom + Javascript und xpath, wäre es möglich, XSLT mit exslt-Erweiterungen im Browser zu schreiben, um document.evaluate zu simulieren (Rückgabe einer Liste von Elementen, die den xpath entsprechen)?

1voto

Pavel Veller Punkte 5983

Ich glaube nicht, dass die standardmäßige XPath-Implementierung des Browsers EXSLT unterstützt. Die auf der EXSLT-Seite erwähnte Javascript-Unterstützung bezieht sich wahrscheinlich darauf, wie Sie Ihre eigene Implementierung der exslt-Funktion mit in-browser.javascript bereitstellen können. Hier ist ein Beispiel, das ich sehr schnell finden konnte .

In Firefox können Sie zum Beispiel Saxon-B als Erweiterung zur Ausführung von XSLT2.0 y Saxon-B hat eingebaute Unterstützung für exslt (im Gegensatz zu Saxon-HE), obwohl Sie wahrscheinlich besser dran sind, wenn Sie nur XSLT/XPath 2.0-Funktionen verwenden . Hier ist die Syntax regulärer Ausdrücke zum Beispiel. Das heißt aber nicht, dass Sie sich auf eine Saxon-B-Erweiterung von Mozilla verlassen müssen, die Ihnen bei Chrome oder anderen Browsern helfen wird.

Daher glaube ich nicht, dass Sie eine browserübergreifende Lösung für die Verwendung von EXSLT-Erweiterungen in Ihrem XPath finden können. Die Konformitätsabschnitt des DOM Level 3 XPath fordert die Unterstützung von XPath 1.0 und erwähnt EXSLT nicht. Die INVALID_EXPRESSION_ERR soll geworfen werden:

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.

Zum Schluss noch ein Bugzilla-Ticket öffnen für Firefox, um die EXSLT-Unterstützung für ihre DOM Level 3 XPath-Implementierung zu öffnen. Es scheint seit 2007 im NEW-Status zu sein. Das Ticket sagt, dass:

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 . Hier ist die Testfall .

--

Wenn ich fragen darf, wofür genau wollten Sie die Regex verwenden? Vielleicht können wir Ihnen helfen, mit einer Kombination aus Standard XPath String-Funktionen ?

--

UPDATE Sie können einen XPath-Runner über XSLT erstellen (wie Sie in der Aktualisierung Ihrer Frage fragen), aber werden nicht die Knoten aus dem Quelldokument zurückgegeben, sondern neue Knoten, die genau so aussehen . XSLT erzeugt ein neues Ergebnisbaumdokument und ich glaube nicht, dass es eine Möglichkeit gibt, Verweise auf die ursprünglichen Knoten zurückzugeben.

Soweit ich das beurteilen kann, sind Mozilla (und Chrome) beide XSLT-Unterstützung nicht nur für XML-Dokumente, die aus externen Quellen geladen werden, sondern auch für DOM-Elemente aus dem angezeigten Dokument. Die Website XSLTProcessor Dokumentation erwähnt, wie tranformToFragment() zum Beispiel, will only produce HTML DOM objects if the owner document is itself an HTMLDocument, or if the output method of the stylesheet is HTML .

Hier ist ein einfacher XPath-Runner, mit dem ich Ihre Ideen getestet habe:

1) Zunächst benötigen Sie eine XSLT-Vorlage, mit der Sie arbeiten können.

<?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>

Ich begann mit dem Aufbau in JavaScript unter Verwendung der document.implementation.createDocument APi, aber ich dachte, es wäre einfacher, es einfach zu laden. FF unterstützt immer noch document.load während Chrome das Laden von Inhalten nur über XHR ermöglicht. Sie müssten Ihren Chrome starten mit --allow-file-access-from-files wenn Sie Dateien mit XHR von Ihrer lokalen Festplatte laden wollen.

2) Sobald wir die Vorlage geladen haben, müssen wir den Wert des Parameters select Attribut des xsl:copy-of Anweisung, um den benötigten XPath auszuführen:

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

Sie können es jetzt mit etwas wie ausführen:

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

Es funktioniert hervorragend für "normale" XPath wie diese //div[@id] (und findet nicht //div[@not-there] ) aber ich bekomme es einfach nicht dazu, die regexp:test Erweiterungsfunktion . Mit dem //div[regexp:test(string(@id), "a")] gibt es keine Fehlermeldung, sondern nur eine leere Menge.

Die Mozilla-Dokumentation schlägt vor ihr XSLT-Prozessor unterstützt EXSLT . Ich könnte mir vorstellen, dass sie hinter den Kulissen ohnehin alle libxml/libxslt verwenden. Das heißt, ich konnte es nicht bekommen, um in Mozilla entweder arbeiten.

Ich hoffe, es hilft.

Gibt es eine Chance, dass Sie mit jQuery regexp ? wahrscheinlich nicht hilfreich für Ihre XPath Builder-Dienstprogramm, aber immer noch ein Weg, um regexp auf HTML-Knoten laufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X