我正在开发一个需要将XML发送到服务器后端的Web应用程序。我想在客户端内部构建一个XML文档,但是使用XML操作例程,而不是将无数字符串附加在一起。我希望jQuery可以帮助我。
假设我需要使用JavaScript生成这个(玩具)XML文档:
<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>
首先,我需要使用“report”根创建某种XML文档对象。我假设其中一个应该很接近,但它们都没有正常工作,和/或我无法弄清楚如何正确使用该对象:
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;
}
现在我想创建和追加元素。我怎么做?我想它是这样的:
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;
}
有什么想法吗?
答案 0 :(得分:63)
第二种方法似乎是一个很好的方法。它旨在使用XML文档。 创建文档对象后,使用标准XML DOM操作方法构建整个文档。
// 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);
这看起来有点冗长,但却是构建XML文档的正确方法。 jQuery实际上并不构造任何XML文档,而只是依赖于innerHTML
属性来解析和重构给定HTML字符串的DOM。这种方法的问题在于,当XML中的标记名称与HTML中的标记名称(如<table>
或<option>
)发生碰撞时,结果可能无法预测。
(编辑:自1.5以来{em> 实际构建一个XML文档jQuery.parseXML(),从而避免了这些问题 - 仅用于解析。)
要减少冗长,请编写一个小帮助程序库,或者编写一个jQuery插件来构建文档。
这是使用递归方法创建XML文档的快速而肮脏的解决方案。
// 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')
)
)
);
返回:
<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>
答案 1 :(得分:26)
如果 使用jQuery来构建XML,请不要解决 的一些想法:
// 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());
输出:
<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>
答案 2 :(得分:2)
我发现Ariel Flesler的XMLWriter构造函数是从头开始创建XML(在内存中)的良好开端,看看这个
http://flesler.blogspot.com/2008/03/xmlwriter-for-javascript.html
实施例
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() );
}
结果
<?xml version="1.0" encoding="ISO-8859-1" standalone="true" ?>
<test foo="bar">Hello World</test>
有几点需要注意,它不会逃避字符串,语法会让coyote变得丑陋。
答案 3 :(得分:1)
你考虑过JSON吗?您可以使用对象保存数据。然后,您可以使用JSON.stringify(obj);
并将其发送到服务器。
一个简单的例子
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
}
答案 4 :(得分:0)
如果可以在具有相同结构的JavaScript对象中表示所需的XML结构,则可以创建此类对象,并使用以下函数将该对象转换为XML:
/* Arguments:
name: name of the root XML-element
val: the data to convert to XML
Returns: XML string
Example: toXml("root", { items: { item: [1, 2] } })
returns: "<root><items><item>1</item><item>2</item></items></root>"
*/
function toXml(name, val) {
const map = {"<":"<", ">":">", "&":"&", "'":"&apos", '"':"""};
if (Array.isArray(val)) return val.map(elem => toXml(name, elem)).join``;
const content = Object(val) === val
? Object.keys(val).map(key => toXml(key, val[key])).join``
: String(val).replace(/[<>&'"]/g, m => map[m]);
return `<${name}>${content}</${name}>`;
}
// Example:
const report = {
submitter: { name: "John Doe" },
students: {
student: [{ name: "Alice", grade: 80 },
{ name: "Bob", grade: 90 }]
}
};
console.log(
'<?xml version="1.0" encoding="UTF-8" standalone="no" ?>' +
toXml("report", report));