2017-07-10 1 views
0

J'écris une application pour visualiser le contenu de quelques bases de données. Cette application devrait être aussi facile que possible à installer et à utiliser, j'ai donc décidé d'utiliser des fichiers XML comme bases de données et de les transformer adéquatement avec XSL via un navigateur. À l'heure actuelle, les fichiers XSL sont programmés pour créer un tableau récapitulatif de chaque base de données et en cliquant sur la première cellule de chaque ligne, une description plus complète de l'ensemble de l'entrée apparaît. Cela signifie que la page contient chaque description complète de chaque enregistrement dans la base de données, mais cette situation ralentit le chargement de la page, ce qui nécessite jusqu'à 5 secondes pour charger quelques centaines d'enregistrements. Étant donné que je prévois d'élargir les bases de données à l'avenir, ce problème est appelé à s'aggraver. Pour réduire la charge, la prochaine étape évidente est de recourir à une sorte de chargement différé, soit en utilisant AJAX ou un iframe (pas vraiment important celui en ce moment et pas le point de la question), mais je rencontre quelques difficultés. Mon idée était d'appeler directement un fichier XML comme ceci:Extraire les paramètres d'URL à partir de XML/XSL

file:///path/to/file/transform.xml?id=23 

Avec transform.xml être:

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="transform.xsl"?> 
<content /> 

Et transform.xsl être:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml"> 
    <xsl:output method="html" version="5" doctype-system="about:legacy-compat" indent="yes" /> 
    <xsl:param name="url" /> 

    <xsl:template match="/"> 
     <html> 
      <body><xsl:value-of select="$url" /></body> 
     </html> 
    </xsl:template> 
</xsl:stylesheet> 

c'est juste En ce moment une preuve de concept, mais cette partie est la pierre angulaire de tout ce qui suit et si cela ne fonctionne pas, alors il est inutile d'aller plus loin de cette façon.

Tout ce que je peux voir en ce moment est une page blanche. J'ai également essayé de changer le nom du paramètre à id, mais la page reste vide. Je sais que cela peut être réalisé facilement avec PHP ou d'autres solutions côté serveur et MySQL serait plus efficace, mais j'ai vraiment besoin de cette application pour être utilisable au moment même du téléchargement. Si mes utilisateurs doivent installer un serveur * AMP, ils ne le feront probablement pas. Un serveur public n'est pas non plus une solution, car j'ai besoin que cette application soit exécutée hors ligne. Une solution JavaScript/jQuery d'un autre côté est parfaitement acceptable, car elle est côté client.

Modifier: La plupart de mon travail est basé sur this question, qui semble fonctionner mais est assez ancien et l'exemple contient l'URL d'une page ASP.

Répondre

0

Depuis le passage des paramètres d'URL à XSL semble irréalisable, j'ai trouvé un autre chemin à travers AJAX. Javascript importe les fichiers XML et XSL, puis filtre le fichier XML de sorte qu'il ne reste qu'un seul élément, puis applique le fichier XSL à la structure XML restante.

Pour ceux qui cherchent l'inspiration avec des problèmes similaires, je vais laisser un exemple simplifié du code que j'utilise. jQuery est requis pour ce code, mais il peut parfaitement fonctionner sans.

page.js (copié sans vergogne de here):

function expand_box(id, tag_to_isolate, XML_file, XSL_file, container) { 
    if($('div#' + id).length == 0) { //first opening 
     var XML = $.ajax({url: XML_file, async: false, dataType: 'xml'}).responseXML.activeElement; 
     var XSL = $.ajax({url: XSL_file, async: false, dataType: 'xml'}).responseXML.activeElement; 
     if(XSL.getElementsByTagName('xsl:include').length == 1) { //bonus, see below* 
      var XSL_temp = $.ajax({url: 'templates.xsl', async: false, dataType: 'xml'}).responseXML.activeElement; 
      $(XSL.getElementsByTagName('xsl:include')).replaceWith(XSL_temp.childNodes); 
     } 
     XML = $(XML).find(tag_to_isolate + '[id=' + id + ']')[0]; 
     if (window.ActiveXObject) { // code for IE 
      var result = XML.transformNode(XSL); 
     } 
     else if (document.implementation && document.implementation.createDocument) { // code for Chrome, Firefox, Opera, etc. 
      var xsltProcessor = new XSLTProcessor(); 
      xsltProcessor.importStylesheet(XSL); 
      var result = xsltProcessor.transformToFragment(XML, document); 
     } 
     $('div#' + panel).append(result); 
     //other code here, e.g. to apply all jQuery functions bound to clicks, ... 
    } 
    $('#' + id).slideDown(); 
} 

* Bonus: Je trouve que javascript XSLTProcessor ne peut pas gérer xsl:include balises, donc je devais les importer manuellement. Le code est assez simple ici car j'utilise un seul fichier xsl pour contenir tous les templates partagés, donc la substitution est automatique, mais elle peut être facilement adaptée pour être plus flexible.

database.xml (pas le même fichier XML indiqué ci-dessus):

<?xml version="1.0" encoding="UTF-8"?> 
<elements> 
    <element id="1"> 
     ... 
    </element> 
    ... 
</elements> 

transform.xsl:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml"> 
    <xsl:template match="/elements/element"> 
     ... 
    </xsl:template> 
    <xsl:include href="templates.xsl" /> 
</xsl:stylesheet> 

En fonction de la base de données utilisée, vous pouvez créer autant de matches au besoin. Je dois dire que mon navigateur m'avertit que les requêtes AJAX synchrones sur le thread principal sont obsolètes à cause des effets négatifs sur les utilisateurs et seront probablement désactivées à l'avenir, donc la réponse pourrait probablement être améliorée, mais j'ai choisi sur Pour avoir des requêtes synchrones car tout se passe sur mon ordinateur, la requête est rapide quelle que soit la taille du fichier. Sur un serveur distant, une requête asynchrone est nécessaire.

0

L'appel d'une transformation à l'aide de l'instruction de traitement xml-stylesheet ne fournit aucun moyen de fournir des paramètres à la transformation. Ainsi, le paramètre prendra sa valeur par défaut, qui est une chaîne de longueur nulle.

Désolé, mais cette conception ne va pas voler.

Je pense que la seule façon d'y parvenir est d'avoir du code Javascript dans la page HTML qui appelle la transformation par programmation.

Une option consiste à utiliser Saxon-JS plutôt que de se fier au moteur XSLT fourni par le navigateur. Cela vous donnera accès aux fonctionnalités XSLT 2.0/3.0 plutôt qu'à seulement 1.0, et dans 2.0 une feuille de style peut accéder à l'URI du document source en utilisant la fonction document-uri().

+0

Le problème que je vois avec Saxon-JS est qu'il nécessite une sorte de compilation de fichiers XSL, ce qui signifie que le code sera probablement fermé. – GRB

+0

Oui, la dépendance aux outils commerciaux est un facteur dont vous devez tenir compte. Vous devez décider si vous préférez utiliser des outils commerciaux développés activement en 2017 ou des outils gratuits qui n'ont pas évolué depuis 2001. –