aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-08-16 15:18:58 +0100
committerMichael Williamson <mike@zwobble.org>2015-08-16 15:18:58 +0100
commitd8c0a72e33e661590cdfea63fcaa0926b2b589ff (patch)
tree49bb2801ef8ab93eb2dbae71776da302e2ccdc29
parent93625f1557428915f7a68156e1edc95b9d849eae (diff)
Basic support for writing XML namespaces
-rw-r--r--lib/xml/writer.js69
-rw-r--r--tests/xml/writer.tests.js30
2 files changed, 68 insertions, 31 deletions
diff --git a/lib/xml/writer.js b/lib/xml/writer.js
index 418a4b9..66cc8de 100644
--- a/lib/xml/writer.js
+++ b/lib/xml/writer.js
@@ -1,36 +1,57 @@
+var _ = require("underscore");
var xmlbuilder = require("xmlbuilder");
exports.writeString = writeString;
-function writeString(root) {
- var builder = xmlbuilder
- .create(root.name, {
- version: '1.0',
- encoding: 'UTF-8',
- standalone: true
- });
- root.children.forEach(function(child) {
- writeNode(builder, child);
- });
- return builder.end();
-}
+function writeString(root, namespaces) {
+ var uriToPrefix = _.invert(namespaces);
+
+ var nodeWriters = {
+ element: writeElement,
+ text: writeTextNode
+ };
-var nodeWriters = {
- element: writeElement,
- text: writeTextNode
-};
+ function writeNode(builder, node) {
+ return nodeWriters[node.type](builder, node);
+ }
-function writeNode(builder, node) {
- return nodeWriters[node.type](builder, node);
-}
+ function writeElement(builder, element) {
+ var elementBuilder = builder.element(mapElementName(element.name), element.attributes);
+ element.children.forEach(function(child) {
+ writeNode(elementBuilder, child);
+ });
+ }
+
+ function mapElementName(name) {
+ var longFormMatch = /^\{(.*)\}(.*)$/.exec(name);
+ if (longFormMatch) {
+ return uriToPrefix[longFormMatch[1]] + ":" + longFormMatch[2];
+ } else {
+ return name;
+ }
+ }
+
+ function writeDocument(root) {
+ var builder = xmlbuilder
+ .create(root.name, {
+ version: '1.0',
+ encoding: 'UTF-8',
+ standalone: true
+ });
+
+ _.forEach(namespaces, function(uri, prefix) {
+ builder.attribute("xmlns:" + prefix, uri);
+ });
+
+ root.children.forEach(function(child) {
+ writeNode(builder, child);
+ });
+ return builder.end();
+ }
-function writeElement(builder, element) {
- var elementBuilder = builder.element(element.name, element.attributes);
- element.children.forEach(function(child) {
- writeNode(elementBuilder, child);
- });
+ return writeDocument(root);
}
function writeTextNode(builder, node) {
diff --git a/tests/xml/writer.tests.js b/tests/xml/writer.tests.js
index a542dc3..6c414c0 100644
--- a/tests/xml/writer.tests.js
+++ b/tests/xml/writer.tests.js
@@ -7,11 +7,11 @@ var test = require("../testing").test;
describe('xml.writer', function() {
test('writing empty root element writes out xml declaration and empty root element', function() {
- assertXmlString(xml.element("root"), '<root/>');
+ assertXmlString(xml.element("root"), {}, '<root/>');
});
test('can write empty child elements', function() {
- assertXmlString(xml.element("root", {}, [xml.element("album"), xml.element("single")]),
+ assertXmlString(xml.element("root", {}, [xml.element("album"), xml.element("single")]), {},
'<root><album/><single/></root>');
});
@@ -22,7 +22,7 @@ describe('xml.writer', function() {
xml.element("song")
])
]);
- assertXmlString(element,
+ assertXmlString(element, {},
'<root><album><year/><song/></album></root>');
});
@@ -30,7 +30,7 @@ describe('xml.writer', function() {
var element = xml.element("root", {}, [
xml.element("album", {"title": "Everything in Transit"})
]);
- assertXmlString(element,
+ assertXmlString(element, {},
'<root><album title="Everything in Transit"/></root>');
});
@@ -40,14 +40,30 @@ describe('xml.writer', function() {
xml.text("Everything in Transit")
])
]);
- assertXmlString(element,
+ assertXmlString(element, {},
'<root><album>Everything in Transit</album></root>');
});
+
+ test('can write child elements with long-form prefix when URI is namespace', function() {
+ var element = xml.element("root", {"m": "music"}, [
+ xml.element("{music}album")
+ ]);
+ assertXmlString(element, {"m": "music"},
+ '<root xmlns:m="music"><m:album/></root>');
+ });
+
+ test('can write child elements with short-form prefix when URI is namespace', function() {
+ var element = xml.element("root", {"m": "music"}, [
+ xml.element("m:album")
+ ]);
+ assertXmlString(element, {"m": "music"},
+ '<root xmlns:m="music"><m:album/></root>');
+ });
});
-function assertXmlString(element, expectedString) {
- assert.equal(writer.writeString(element),
+function assertXmlString(element, namespaces, expectedString) {
+ assert.equal(writer.writeString(element, namespaces),
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
expectedString);
}