2010-07-07 20 views
33

Estoy trabajando en una aplicación web que necesita enviar XML a un servidor back-end. Me gustaría construir un documento XML en memoria en el lado del cliente, pero usando rutinas de manipulación XML, en lugar de agregar innumerables cadenas. Espero que jQuery pueda ayudarme.Generar documento XML en memoria con JavaScript

Digamos que necesito para generar este (de juguete) documento XML con 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> 

Para empezar, tengo que crear algún tipo de un objeto documento XML con la raíz "informe". Estoy asumiendo que uno de ellos debe estar cerca, pero ninguno de ellos funciona del todo bien, y/o no acabo de encontrar la manera de utilizar el objeto correctamente:

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

Ahora quieren crear y añadir elementos. ¿Cómo puedo hacer eso? Imagino que es algo como esto:

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

¿Alguna idea?

+0

Asegúrese de que usted echa un vistazo solución @AlexanderN al final si quieres un método de gran plugin para js crear estructuras XML, incluidos atributos y CDATA. – whyoz

Respuesta

26

Sin abordar si usted debe utilizar jQuery para construir XML, aquí están algunas ideas sobre cómo es posible hacerlo:

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

Salida:

<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 problema con este enfoque es que en HTML los nombres de las etiquetas son insensibles a mayúsculas y minúsculas, mientras que en XML son sensibles a mayúsculas y minúsculas. Por lo tanto, jQuery convertirá todas las etiquetas a minúsculas, lo que podría no ser lo que deseas. – Jeroen

+1

Buena advertencia "Sin tratar de indicar si _debería_ ...", me hizo reflexionar y me ayudó – robert4

1

¿Usted ha considerado JSON ? Puede guardar los datos usando objetos. Entonces podría usar JSON.stringify(obj); y enviar eso al servidor.

un ejemplo sencillo

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 no es capaz de almacenar muchas estructuras de datos, mientras que XML puede almacenar cualquier cosa. – Dima

60

El segundo enfoque parece un buen camino a seguir. Fue diseñado para trabajar con documentos XML. Una vez que haya creado el objeto del documento, utilice los métodos estándar de manipulación XML DOM para construir todo el documento.

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

Esto puede parecer un poco detallado pero es la forma correcta de compilar el documento XML. jQuery en realidad no construye ningún documento XML, sino que simplemente se basa en la propiedad innerHTML para analizar y reconstruir un DOM dado una cadena HTML. El problema con este enfoque es que cuando los nombres de las etiquetas en su XML chocan con los nombres de las etiquetas en HTML como <table> o <option>, los resultados pueden ser impredecibles. (EDIT: desde 1,5 hay jQuery.parseXML() cuales qué realmente construir un documento XML y por lo tanto evita estos problemas - para analizar solamente.)

Para reducir la verbosidad, escribir una pequeña biblioteca de ayuda, o tal vez un plugin de jQuery para construir el documento

Aquí hay una solución rápida y sucia para crear un documento XML utilizando un enfoque recursivo.

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

Devuelve:

<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

Esto puede o no ser rápido + sucio, ¡pero definitivamente es muy bonito! – Tao

+8

Combínelo con 'new XMLSerializer(). SerializeToString (yourXml)' y forma una excelente manera de compilar documentos estructurados para enviar mensajes AJAX. ¡Magnífico! –

+0

Esto es lo que necesito pero de alguna manera no pude hacer que funcione, ¿este http://jsfiddle.net/vquyT/1/ tampoco funciona? ¿Podrías actualizar este enlace o me falta algo? –

2

que he encontrado función XMLWriter constructor de Ariel Flesler para ser un buen punto de partida para la creación de XML desde cero (en la memoria), echar un vistazo a este

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

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

Resultado

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

Un par de advertencias, no escapa cuerdas y la sintaxis puede obtener coyote ++ feo.

+0

'' 'ReferenceError: XMLWriter no está definido''' (Versión de Chrome 30.0.1599.101 m) –

+0

@Michal Stefanow ¿Incluyó la función XmlWriter? –

+0

No hice clic en el enlace. Pensé que el ejemplo es autónomo. –

4

Nota:

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

jQuery crea elementos en minúsculas, y $("<topMenu />")$("<topmenu />") crea elementos iguales <topmenu />

Cuestiones relacionadas