-
Notifications
You must be signed in to change notification settings - Fork 1
Api Reference (1.0)
The constructor creates a serializer instance using the optional behavior
object.
- behavior
- arrays
- attributes
- cdatas
- texts
See the serializer.behavior section for details.
Tells serialize
and deserialize
methods how to behave with fields or XML elements. The behavior
object contains two fields:
The array mappers relate a field path with its child item name. The key must be the complete path to the corresponding field name, including all parents up to the XML root element name separated by dots(.) (that was the field path definition). The value part is the name of the array item.
A behavior
object example with two defined array fields:
var Serializer = require("damn-simple-xml");
var serializer = new Serializer({
arrays: {
"organization.employees": "employee",
"organization.customers": "customer"
}
});
When deserializing XML and encountering the employees
element inside the root element named organisation
, a JavaScript array will be created and each child elements will be added to that array (regardless of the element and array item name). When serializing, each children of the employees
will be serialized inside an employee
XML element. The same goes for customers
.
(since 1.2.0)
It is also possible to declare an element name to be deserialized as an array at any depth within the XML path. To do that use the "*." declaration prior to the element name you want to define as an array. For example:
var serializer = new Serializer({
arrays: {
"*.children": "item"
}
});
The aforementioned declaration will serialize all elements with "item" as name within an array named "children" anywhere within the object graph. The same goes for deserialization.
The attribute mappers relate a field path and an array of field names to be serialized as attributes within the parent element. An attribute can be of any basic type and of the Date
type. Objects and arrays are prohibited and an error object will be returned in the callback function if such a field would be declared as an attribute. The attribute
behavior have no effect on deserialization.
A behavior
object example with attributes field definitions:
var Serializer = require("damn-simple-xml");
var serializer = new Serializer({
arrays: {
"organization.employees": "employee",
"organization.employees.employee.emails": "email"
}
attributes: {
"organization.employees.employee.emails.email": ["type"]
}
});
When deserializing and encountering the field type
inside the email
field of the organization
object hierarchy, the attribute type
will be added to the email
element with its corresponding value between double quotes(").
Not yet supported
(since 1.1.2)
When serializing, fields marked as "cdata" will be rendered with the surrounding "" markers. The "cdatas" field of the behavior
object are declared as a path to an object field and an array of fields that should be serialized as CDATA. For example:
var serialized = new Serializer({
cdatas: {
"employees.employee": ["notes", "remarks"]
}
});
In the previous example, fields "notes" and "remarks" from the "employee" object will both be serialized as CDATA.
Not yet supported
The text mappers relate field path to the field inside of it that will be dumped directly as text without enclosing tags. Object and array fields are prohibited and an Error object will be sent to the callback function if such fields where to be declared as text. Any non-string fields will be stringified. Date type will be ISOStringified (I mean... yeah... you know).
A behavior
object with texts field definition
var Serializer = require("damn-simple-xml");
var serializer = new Serializer({
arrays: {
"organization.employees": "employee",
}
attributes: {
"organization.employees.employee": "notes"
}
});
When serializing using the previous serializer
, the content of the notes
field from the employee field will be dumped directly as text within the employee node. When deserializing, any text directly encountered within the employee element will be concatenated in the notes
field, separated by spaces.
Not yet supported
Creates a JavaScript object based on the xml
parameter.
- xml: The XML input data to be deserialized into an object. This parameter can be either a string or a stream.Readable instance.
-
callback: a function(err, root) called when the deserialization is complete. If an error occurs, the
err
parameter will contain the an Error object detailing the issue. If successful, the err parameter will be null and the deserialization result will be in theroot
object. See root object documentation.
Deserialization will consider all attributes and sub nodes of the current element as fields of the currently deserialized object. Each values are parsed and automatically cast to the type they are the most likely to be.
In the absence of a corresponding behavior.arrays
field path definition, when an XML element is encountered and there is already a corresponding field in the deserialized object, the parent field is changed from an object to an array containing both XML elements. Each other child element will then be deserialized as an array item of the current field, regardless of its name. This behavior is called automatic array discovery. This example should make that point clear:
XML string:
<employee id="123">
<firstName>John</firstName>
<lastName>Doe</lastName>
<dateOfBirth>1984-03-12T00:00:00.000Z</dateOfBirth>
<languages>
<language>Java</language>
<language>C++</language>
<language>C#</language>
<language>JavaScript</language>
</languages>
</employee>
root.data
:
{
id: 123,
firstName: "John",
lastName: "Doe",
dateOfBirth: "1984-03-27T00:00:00.000Z",
languages: ["Java", "C++", "C#", "JavaScript"]
}
Given the absence of a second element with the same name, the following deserialized object will occurs:
<employee id="123">
<firstName>John</firstName>
<lastName>Doe</lastName>
<dateOfBirth>1984-03-12T00:00:00.000Z</dateOfBirth>
<languages>
<language>Java</language>
</languages>
</employee>
root.data
:
{
id: 123,
firstName: "John",
lastName: "Doe",
dateOfBirth: "1984-03-27T00:00:00.000Z",
languages: {
language: "Java"
}
}
To prevent this, all arrays should be declared beforehand with the following behavior.arrays
:
var Serializer = require("damn-simple-xml");
var serializer = new Serializer({
arrays: {
"employee.languages": "language"
}
})
The deserialize
function needs that the arrays
object returns a "truish" value (non-null and non-empty string) when checking for behavior.arrays[fieldPath]
. The actual array item name part is used only for serialization purpose.
So given the behavior
in the previous example, the resulting employee.languages
field will turn back to the expected array:
{
id: 123,
firstName: "John",
lastName: "Doe",
dateOfBirth: "1984-03-27T00:00:00.000Z",
languages: ["Java"]
}
When in-line text is encountered within a set of XML element or inside an element with at least one attribute, a field named _text
will be automatically created for the current object with the trimmed text. Each in-line text met thereafter will be trimmed and concatenated with a space to the _text
field. If a texts
field path is mapped to a field name, instead of using the default _text
field, the specified field name will be used.
<employee>
This is
<firstName>John</firstName>
some text
<lastName>Doe</lastName>
interleaved with
<email type="personal">[email protected]</email>
elements
</employee>
Will result in:
{
_text: "This is some text interleaved with elements",
name: "employee",
data: {
firstName: "John",
lastName: "Doe",
email: {
type: "personal",
_text: "[email protected]"
}
}
Generates XML given the root name and data.
-
root
- name: The name of the root element where the data object will be serialized.
- data: The object to be serialized.
-
callback: a function(err, xmlpart, level) called during serialization each time some XML text is available. If an error occurs, the
err
parameter will contain the an Error object detailing the issue. When invoked during serialization, the level parameter value will be above 0. Once the level reaches 0, it means that the serialization is over.
The serialization dumps every elements one after the other in one long line. This is a design choice. We consider XML content beatification out of scope of the current library. To make the resulting XML human readable (quite easier to debug), just copy-paste the resulting XML data inside Notepad++ and format it using the XML plug-in. If you are working on some other OS than Windows (as I do most of the time) there is a plethora of XML formatter around the Web for your convenience.
By default, if no behavior
object is specified at construction, the root.data
object will be serialized in a root.name
element. After that, each fields of the root.data
object will be recursively serialized in an element of the same name. When _text
element is encountered, it is dumped in the parent element without enclosing XML tags.
When serializing, if there is no array field definition corresponding to the current array field name in the serializer behavior
object, array items will be named according to the parent item name concatenated with "Item". For example:
serializer.serialize({
name: "employees",
data: [
{
id: 123,
department: "Marketting",
fullname: "John Doe"
},
{
id: 456,
department: "Administration",
fullname: "Jane Doe"
}
]
});
will result in (XML data is formatted for the example purpose):
<employees>
<employeesItem>
<id>123</id>
<department>Marketting</department>
<fullname>John Doe</fullname>
</employeesItem>
<employeesItem>
<id>456</id>
<department>Administration</department>
<fullname>Jane Doe</fullname>
</employeesItem>
</employees>
The following example shows how to control both array names and attributes with the following behavior
object given to the constructor:
var Serializer = require("damn-simple-xml");
var serializer = new Serializer({
arrays: {
"employees" : "employee"
},
attributes: {
"employees.employee": ["id", "department"]
}
});
will result in:
<employees>
<employee id="123" department="Marketting">
<fullname>John Doe</fullname>
</employee>
<employee id="456" department="Administration">
<fullname>Jane Doe</fullname>
</employee>
</employees>
It is important to note that the serialization callback is called repetitively as soon as a XML string chunks is available (xmlpart
paramter). To construct the whole XML document, simply concatenate all chunks in one master variable. Dumping to a stream would be a great option as well. When done, the callback will be invoked with the level
parameter value at 0. It indicates that the serialization is over for the current serialization function call.
Serialization callback example
var xml = "";
serializer.serialize({
name: "employees",
data: employeeList
}, function(err, xmlpart, level) {
if (err) {
console.log(err);
return;
}
xml += xmlpart;
if (level === 0) {
// We are done serializing! Lets see what our XML look like.
console.log(xml);
}
});