使用 JavaScript 在内存中生成 XML 文档
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3191179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generate XML document in-memory with JavaScript
提问by Shaggy Frog
I am working on a Web application that needs to send XML to a server backend. I'd like to build a XML document in-memory on the client-side, but using XML manipulation routines, instead of appending countless strings together. I'm hoping jQuery can help me out.
我正在开发一个需要将 XML 发送到服务器后端的 Web 应用程序。我想在客户端的内存中构建一个 XML 文档,但使用 XML 操作例程,而不是将无数的字符串附加在一起。我希望 jQuery 可以帮助我。
Let's say I need to generate this (toy) XML document with JavaScript:
假设我需要用 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>
To start, I need to create some kind of an XML document object with the "report" root. I'm assuming one of these should be close, but none of them work quite right, and/or I can't quite figure out how to use the object properly:
首先,我需要使用“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;
}
Now I want to create and append elements. How do I do that? I imagine it's something like this:
现在我想创建和附加元素。我怎么做?我想它是这样的:
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;
}
Any ideas?
有任何想法吗?
采纳答案by rath
Without addressing whether you shoulduse jQuery to build XML, here are some ideas on howyou might do it:
没有解决是否应该使用 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());
Output:
输出:
<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>
回答by Anurag
The second approach seems a good way to go. It was designed to work with XML documents. Once you have the document object created, use the standard XML DOM manipulation methods to construct the entire document.
第二种方法似乎是一个很好的方法。它旨在处理 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);
This may seem a little verbose but is the right way to build the XML document. jQuery does not actually construct any XML document, but just relies on the innerHTMLproperty to parse and reconstruct a DOM given an HTML string. The problem with that approach is that when tag names in your XML collide with tag names in HTML such as <table>or <option>, then the results can be unpredictable.
(EDIT: since 1.5 there's jQuery.parseXML()which doesactually construct an XML document and thus avoids these problems — for parsing only.)
这可能看起来有点冗长,但却是构建 XML 文档的正确方法。jQuery 实际上并不构造任何 XML 文档,而只是依赖于innerHTML给定 HTML 字符串的属性来解析和重建 DOM。这种方法的问题在于,当 XML 中的标记名称与 HTML 中的标记名称(例如<table>或 )发生冲突时<option>,结果可能无法预测。(编辑:从 1.5 开始,有jQuery.parseXML()它确实构造了一个 XML 文档,从而避免了这些问题 - 仅用于解析。)
To cut down on the verboseness, write a small helper library, or maybe a jQuery plugin to construct the document.
为了减少冗长,编写一个小的帮助库,或者一个 jQuery 插件来构建文档。
Here's a quick and dirty solution to creating a XML document using a recursive approach.
这是使用递归方法创建 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')
)
)
);
Returns:
返回:
<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>?
回答by Alex Nolasco
I've found Ariel Flesler's XMLWriter constructor function to be a good start for creating XML from scratch (in memory), take a look at this
我发现 Ariel Flesler 的 XMLWriter 构造函数是从头(在内存中)创建 XML 的良好开端,看看这个
http://flesler.blogspot.com/2008/03/xmlwriter-for-javascript.html
http://flesler.blogspot.com/2008/03/xmlwriter-for-javascript.html
Example
例子
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() );
}
Result
结果
<?xml version="1.0" encoding="ISO-8859-1" standalone="true" ?>
<test foo="bar">Hello World</test>
A couple of caveats, it doesn't escape strings and the syntax can get coyote++ ugly.
几个警告,它不会转义字符串,并且语法可能会使 coyote++ 变得丑陋。
回答by qw3n
Have you considered JSON? You could save the data using objects. Then you could use JSON.stringify(obj);and send that to the server.
你考虑过 JSON 吗?您可以使用对象保存数据。然后您可以使用JSON.stringify(obj);并将其发送到服务器。
a simple example
一个简单的例子
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
}
回答by trincot
If your desired XML structure can be represented in a JavaScript object having the same structure, then you could create such an object and use the following function to convert that object to XML:
如果您想要的 XML 结构可以在具有相同结构的 JavaScript 对象中表示,那么您可以创建这样一个对象并使用以下函数将该对象转换为 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));

