2010-07-07 5 views
33

Je travaille sur une application Web qui doit envoyer du code XML à un serveur principal. Je voudrais construire un document XML en mémoire sur le côté client, mais en utilisant des routines de manipulation XML, au lieu d'ajouter d'innombrables chaînes ensemble. J'espère que jQuery peut m'aider.Générer un document XML en mémoire avec JavaScript

Disons que je dois générer ce document XML (jouet) avec JavaScript:

<report> 
    <submitter> 
     <name>John Doe</name> 
    </submitter> 
    <students> 
     <student> 
      <name>Alice</name> 
      <grade>80</grade> 
     </student> 
     <student> 
      <name>Bob</name> 
      <grade>90</grade> 
     </student> 
    </students> 
</report> 

Pour commencer, je dois créer une sorte d'un objet de document XML avec la racine « rapport ». Je suppose un d'eux doit être proche, mais aucun d'entre eux travaillent tout à fait raison, et/ou je ne peux pas tout à fait comprendre comment utiliser correctement l'objet:

function generateDocument1() 
{ 
    var report = $('<report></report>'); 
    return report; 
} 

function generateDocument2() 
{ 
    var report = document.implementation.createDocument(null, "report", null); 

    return new XMLSerializer().serializeToString(report); 
} 

function createXmlDocument(string) 
{ 
    var doc; 
    if (window.DOMParser) 
    { 
     parser = new DOMParser(); 
     doc = parser.parseFromString(string, "application/xml"); 
    } 
    else // Internet Explorer 
    { 
     doc = new ActiveXObject("Microsoft.XMLDOM"); 
     doc.async = "false"; 
     doc.loadXML(string); 
    } 
    return doc; 
} 

function generateDocument3() 
{ 
    var report = createXmlDocument('<report></report>'); 

    return report; 
} 

Maintenant, je veux créer et ajouter éléments. Comment je fais ça? J'imagine que c'est quelque chose comme ceci:

function generateReportXml() 
{ 
    // Somehow generate the XML document object with root 
    var report = /*???*/; 

    // Somehow create the XML nodes 
    var submitter = /*???*/; 
    var name = /*???*/; 

    // Somehow append name to submitter, and submitter to report 
    submitter.append(name); /*???*/ 
    report.append(submitter); /*???*/ 

    // ... append the rest of the XML 

    return report; 
} 

Des idées?

+0

Assurez-vous de vérifier la solution @AlexanderN à la fin si vous voulez la méthode d'un grand plugin créer des structures XML, y compris des attributs et CDATA. – whyoz

Répondre

26

Sans aborder si vous devez utiliser jQuery pour construire XML, voici quelques idées sur comment vous pouvez le faire:

// Simple helper function creates a new element from a name, so you don't have to add the brackets etc. 
$.createElement = function(name) 
{ 
    return $('<'+name+' />'); 
}; 

// JQ plugin appends a new element created from 'name' to each matched element. 
$.fn.appendNewElement = function(name) 
{ 
    this.each(function(i) 
    { 
     $(this).append('<'+name+' />'); 
    }); 
    return this; 
} 

/* xml root element - because html() does not include the root element and we want to 
* include <report /> in the output. There may be a better way to do this. 
*/ 
var $root = $('<XMLDocument />'); 

$root.append 
(
    // one method of adding a basic structure 
    $('<report />').append 
    (
     $('<submitter />').append 
     (
      $('<name />').text('John Doe') 
     ) 
    ) 
    // example of our plugin 
    .appendNewElement('students') 
); 

// get a reference to report 
var $report = $root.find('report'); 

// get a reference to students 
var $students = $report.find('students'); 
// or find students from the $root like this: $root.find('report>students'); 

// create 'Alice' 
var $newStudent = $.createElement('student'); 
// add 'name' element using standard jQuery 
$newStudent.append($('<name />').text('Alice')); 
// add 'grade' element using our helper 
$newStudent.append($.createElement('grade').text('80')); 

// add 'Alice' to <students /> 
$students.append($newStudent); 

// create 'Bob' 
$newStudent = $.createElement('student'); 
$newStudent.append($('<name />').text('Bob')); 
$newStudent.append($.createElement('grade').text('90')); 

// add 'Bob' to <students /> 
$students.append($newStudent); 

// display the markup as text 
alert($root.html()); 

Sortie:

<report> 
    <submitter> 
     <name>John Doe</name> 
    </submitter> 
    <students> 
     <student> 
      <name>Alice</name> 
      <grade>80</grade> 
     </student> 
     <student> 
      <name>Bob</name> 
      <grade>90</grade> 
     </student> 
    </students> 
</report> 
+4

Un problème avec cette approche est que les noms de balises HTML sont insensibles à la casse, alors qu'en XML, ils sont sensibles à la casse. Par conséquent, jQuery convertira toutes les balises en minuscules, ce qui pourrait ne pas être ce que vous voulez. – Jeroen

+1

Bon avertissement "Sans vous demander si vous deviez ...", cela m'a fait réfléchir et aidé – robert4

1

Avez-vous envisagé JSON ? Vous pouvez enregistrer les données en utilisant des objets. Ensuite, vous pouvez utiliser JSON.stringify(obj); et l'envoyer au serveur.

un exemple simple

var obj = new student('Alice',80); 

function student(a,b){ 
    this.name=a; 
    this.grade=b; 
} 

function sendToServer(){ 
    var dataString = JSON.stringify(obj); 
    //the HTTP request 
} 
+0

JSON n'est pas capable de stocker beaucoup de structures de données, tandis que XML peut stocker n'importe quoi. – Dima

60

La deuxième approche semble une bonne façon d'aller. Il a été conçu pour fonctionner avec des documents XML. Une fois que vous avez créé l'objet document, utilisez les méthodes de manipulation DOM XML standard pour construire le document entier.

// creates a Document object with root "<report>" 
var doc = document.implementation.createDocument(null, "report", null); 

// create the <submitter>, <name>, and text node 
var submitterElement = doc.createElement("submitter"); 
var nameElement = doc.createElement("name"); 
var name = doc.createTextNode("John Doe"); 

// append nodes to parents 
nameElement.appendChild(name); 
submitterElement.appendChild(nameElement); 

// append to document 
doc.documentElement.appendChild(submitterElement); 

Cela peut sembler un peu bavard, mais c'est la bonne façon de construire le document XML. jQuery ne construit réellement aucun document XML, mais s'appuie simplement sur la propriété innerHTML pour analyser et reconstruire un DOM à partir d'une chaîne HTML. Le problème avec cette approche est que lorsque les noms de balise dans votre XML entrent en collision avec les noms de balises en HTML tels que <table> ou <option>, les résultats peuvent être imprévisibles. (EDIT: depuis 1.5, il y a jQuery.parseXML() qui ne construire en fait un document XML et évite ainsi ces problèmes - pour analyser seulement).

Pour réduire la verbosité, écrire une petite bibliothèque d'aide, ou peut-être un plugin jQuery pour construire le document.

Voici une solution simple et rapide pour créer un document XML en utilisant une approche récursive.

// use this document for creating XML 
var doc = document.implementation.createDocument(null, null, null); 

// function that creates the XML structure 
function Σ() { 
    var node = doc.createElement(arguments[0]), text, child; 

    for(var i = 1; i < arguments.length; i++) { 
     child = arguments[i]; 
     if(typeof child == 'string') { 
      child = doc.createTextNode(child); 
     } 
     node.appendChild(child); 
    } 

    return node; 
}; 

// create the XML structure recursively 
Σ('report', 
    Σ('submitter', 
     Σ('name', 'John Doe') 
    ), 
    Σ('students', 
     Σ('student', 
      Σ('name', 'Alice'), 
      Σ('grade', '80') 
     ), 
     Σ('student', 
      Σ('name', 'Bob'), 
      Σ('grade', '90') 
     ) 
    ) 
); 

Retours:

<report>​ 
    <submitter>​ 
     <name>​John Doe​</name>​ 
    </submitter>​ 
    <students>​ 
     <student>​ 
      <name>​Alice​</name>​ 
      <grade>​80​</grade>​ 
     </student>​ 
     <student>​ 
      <name>​Bob​</name>​ 
      <grade>​90​</grade>​ 
     </student>​ 
    </students>​ 
</report>​ 

See example

+4

Cela peut ou peut ne pas être rapide + sale, mais c'est vraiment très joli! – Tao

+8

Combinez avec 'new XMLSerializer(). SerializeToString (yourXml)' et constitue un excellent moyen de créer des documents structurés pour envoyer des messages AJAX. Superbe! –

+0

C'est ce dont j'ai besoin mais d'une manière ou d'une autre je ne pouvais pas le faire fonctionner, ce http://jsfiddle.net/vquyT/1/ ne fonctionne pas non plus? Pourriez-vous mettre à jour ce lien ou ai-je oublié quelque chose? –

2

J'ai trouvé la fonction constructeur XMLWriter Ariel Flesler être un bon point de départ pour la création XML à partir de zéro (en mémoire), jetez un oeil à ce

http://flesler.blogspot.com/2008/03/xmlwriter-for-javascript.html

exempl e

function test(){  
    // XMLWriter will use DOMParser or Microsoft.XMLDOM 
    var v = new XMLWriter(); 
    v.writeStartDocument(true); 
    v.writeElementString('test','Hello World'); 
    v.writeAttributeString('foo','bar'); 
    v.writeEndDocument(); 
    console.log(v.flush()); 
} 

Résultat

<?xml version="1.0" encoding="ISO-8859-1" standalone="true" ?> 
<test foo="bar">Hello World</test> 

Quelques mises en garde, il n'échappe pas à cordes et la syntaxe peut obtenir coyote ++ laid.

+0

'' 'ReferenceError: XMLWriter is not defined''' (Version Chrome 30.0.1599.101 m) –

+0

@Michal Stefanow avez-vous inclus la fonction XmlWriter? –

+0

Je n'ai pas cliqué sur le lien. Je pensais que l'exemple est autonome. –

4

Note:

$.createElement = function(name) 
{ 
    return $('<'+name+' />'); 
}; 

jquery crée des éléments en minuscules, $("<topMenu />") et $("<topmenu />") crée des éléments égaux <topmenu />

Questions connexes