Reputation: 2261
I'm looking for a JavaScript library that can deserialize/unmarshal XML (strings or DOM) to JavaScript classes in a way similar to the .NET XmlSerializer's Deserialize method.
The functionality I'm looking for:
For example, the following XML:
<root textAttribute='text1' numberAttribute='1' attributeToIgnore1='ignored1' attributeToIgnore2='ignored2'>
<children>
<child>text2</child>
<child>text3</child>
</children>
<childToIgnore>ignored3</childToIgnore>
</root>
used with JavaScript definitions similar to these:
function RootClass() {
this.stringProperty = "";
this.integerProperty = 0;
this.collectionProperty = [];
}
function ChildClass() {
this.stringProperty = "";
}
should produce JavaScript objects similar to the following:
var result = new RootClass();
result.textProperty = "text1";
result.integerProperty = 1;
result.collectionProperty = [];
result.collectionProperty[0] = new ChildClass();
result.collectionProperty[0].textProperty = "text2";
result.collectionProperty[1] = new ChildClass();
result.collectionProperty[1].textProperty = "text3;
An example of .NET (C#) code that does the same would be something like (see this .NET Fiddle for a working example):
public class Program
{
public static void Main()
{
var result = Serializer.Deserialize();
Console.WriteLine("text: {0}", result.StringProperty);
Console.WriteLine("number: {0}", result.IntegerProperty);
Console.WriteLine("enum: {0}", result.EnumProperty);
Console.WriteLine("child[0].Value: {0}", result.CollectionProperty[0].Value);
Console.WriteLine("other@[0]: {0}", result.OtherAttributes[0].InnerText);
Console.WriteLine("other*[0]: {0}", result.OtherElements[0].InnerText);
}
}
public static class Serializer
{
public static RootClass Deserialize()
{
var type = typeof (RootClass);
var serializer = new XmlSerializer(type);
var xmlString = @"
<root textAttribute='text1' numberAttribute='1' enumAttribute='item1' attributeToIgnore1='ignored1' attributeToIgnore2='ignored2'>
<children>
<child>text2</child>
<child>text3</child>
</children>
<childToIgnore>ignored3</childToIgnore>
</root>";
using (var stringReader = new StringReader(xmlString))
{
return serializer.Deserialize(stringReader) as RootClass;
}
}
}
[XmlRoot("root")]
public class RootClass
{
[XmlAttribute("textAttribute")]
public string StringProperty;
[XmlAttribute("numberAttribute")]
public int IntegerProperty;
[XmlAttribute("enumAttribute")]
public Enumeration EnumProperty;
[XmlAnyAttribute]
public XmlAttribute[] OtherAttributes;
[XmlArray("children")]
[XmlArrayItem("child")]
public Collection<ChildClass> CollectionProperty;
[XmlAnyElement]
public XmlElement[] OtherElements;
}
public enum Enumeration
{
[XmlEnum("item1")]
Item1,
[XmlEnum("item2")]
Item2
}
public class ChildClass
{
[XmlText]
public string Value;
}
Upvotes: 2
Views: 1633
Reputation: 2261
Jsonix by Alexey Valikov (source, guide) can deserialize XML to JavaScript based on configurable mapping.
I've contributed code to support deserializing custom classes using instance factories. This will hopefully make it into the next release of Jsonix (2.0.11).
var input = "<element1 attribute1='value1' />";
var Class1 = function () {};
Class1.prototype.toString = function () {
return this.Property1;
};
var mapping = {
elementInfos: [{
elementName: "element1",
typeInfo: new Jsonix.Model.ClassInfo({
name: "Element1",
instanceFactory: Class1,
propertyInfos: [
new Jsonix.Model.AttributePropertyInfo({
name: "Property1",
attributeName: "attribute1"
})
]
})
}]
};
var context = new Jsonix.Context([mapping]);
var unmarshaller = context.createUnmarshaller();
var result = unmarshaller.unmarshalString(input).value;
console.log(result.toString()); // logs "value1"
A longer working example on JSFiddle uses XML from question.
Upvotes: 3