Recently I spent some time building dynamic wrapper around XElement
and XDocument
for one of my projects, you can take a look at it here.
Idea exactly the same but I split implementation into two separate classes: DynamicXmlReader
and DynamicXmlWriter
, where former could only read elements and attributes and later could add subelements and attributes. And DynamicXmlReader
throws an exception if it could not find appropriate sub element or attribute but DynamicXmlWriter
adds them into underlying XElement
.
For example, here two of my unit tests where I'm using sample from Jon Skeet's book:
[TestCase]
public void SkeetBookXmlTest()
{
string books =
@"<books>
<book name=""Mortal Engines"">
<author name=""Philip Reeve"" />
</book>
<book name=""The Talisman"">
<author name=""Stephen King"" />
<author name=""Peter Straub"" />
</book>
<book name=""Rose"">
<author name=""Holly Webb"" />
<excerpt>Rose was remembering the illustrations from Morally Instructive Tales for the Nursery.</excerpt>
</book>
</books>";
dynamic dynamicXml = XElement.Parse(books).AsDynamic();
Assert.That(dynamicXml.book[0]["name"].Value, Is.EqualTo("Mortal Engines"));
Assert.That(dynamicXml.book[0].author["name"].Value, Is.EqualTo("Philip Reeve"));
Assert.That(dynamicXml.book[2]["name"].Value, Is.EqualTo("Rose"));
Assert.That((string)dynamicXml.book[2].excerpt, Is.EqualTo("Rose was remembering the illustrations from Morally Instructive Tales for the Nursery."));
}
Or another unit test that creates exactly the same xml document:
[TestCase]
public void SkeetBookXmlTest()
{
// Jon Skeet in his C# in Depth used following sample
string books =
@"<books>
<book name=""Mortal Engines"">
<author name=""Philip Reeve"" />
</book>
<book name=""The Talisman"">
<author name=""Stephen King"" />
<author name=""Peter Straub"" />
</book>
<book name=""Rose"">
<author name=""Holly Webb"" />
<excerpt>Rose was remembering the illustrations from Morally Instructive Tales for the Nursery.</excerpt>
</book>
</books>";
// Lets create this data dynamically
XElement element = new XElement("books");
dynamic dynamicXml = element.AsDynamicWriter();
dynamicXml.book[0]["name"] = "Mortal Engines";
dynamicXml.book[0].author["name"] = "Philip Reeve";
dynamicXml.book[1]["name"] = "The Tailisman";
dynamicXml.book[1].author[0]["name"] = "Stephen King";
dynamicXml.book[1].author[1]["name"] = "Peter Straub";
dynamicXml.book[2]["name"] = "Rose";
dynamicXml.book[2].author["name"] = "Holly Webb";
dynamicXml.book[2].excerpt = "Rose was remembering the illustrations from Morally Instructive Tales for the Nursery.";
Console.WriteLine(element);
Assert.That(dynamicXml.book[0]["name"].Value, Is.EqualTo("Mortal Engines"));
Assert.That(dynamicXml.book[0].author["name"].Value, Is.EqualTo("Philip Reeve"));
Assert.That(dynamicXml.book[2]["name"].Value, Is.EqualTo("Rose"));
Assert.That((string)dynamicXml.book[2].excerpt, Is.EqualTo("Rose was remembering the illustrations from Morally Instructive Tales for the Nursery."));
}