How to save and get values from an Xml without cast? - c#

Something which I really hate is to cast each element or attribute value from a Xml file.
This momment, I'm creating in hundreds of modules a methods where specifies how to convert an object into a XmlFile. Believe, this is very tired. So I'm thinking in an alternative.
I was investigating about XSD, I'm not sure if this will be my salvation. I'm using Linq to Xml to save and get the values. I mean, my objects are composed like this:
- Foo1 : Foo
- Range1 : Range
- X : int
- Y : int
- ...
As you can see, they have many nodes. Is there another alternative to do this? I mean, strongly types.

You can try these XElement extension methods: http://searisen.com/xmllib/extensions.wiki
Here is an example of the power of it, given this xml from another post:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<PatchCreation
Id="224C316C-5894-4771-BABF-21A3AC1F75FF"
CleanWorkingFolder="yes"
OutputPath="patch.pcp"
WholeFilesOnly="yes">
<PatchInformation
Description="Update Patch"
Comments="Update Patch"
ShortNames="no"
Languages="1033"
Compressed="yes"
Manufacturer="me"/>
<PatchMetadata
AllowRemoval="yes"
Description="Update Patch"
ManufacturerName="me"
TargetProductName="Update"
MoreInfoURL="http://andrewherrick.com/"
Classification="Update"
DisplayName="Update Patch"/>
<Family DiskId="5000"
MediaSrcProp="Sample"
Name="Update"
SequenceStart="5000">
<UpgradeImage SourceFile="c:\new.msi" Id="PatchUpgrade">
<TargetImage SourceFile="c:\old.msi" Order="2" Id="PatchUpgrade" IgnoreMissingFiles="no" />
</UpgradeImage>
</Family>
<PatchSequence PatchFamily="SamplePatchFamily"
Sequence="1.0.0.0"
Supersede="yes" />
</PatchCreation>
</Wix>
This sets the value of the UpgradeImage tag's SourceFile Attribute and the TargetImage tag inside the UpgradeImage and its SourceFile.
XElement wix = XElement.Load(xmlFile1.FullName);
wix.Set("PatchCreation/Family/UpgradeImage/SourceFile", "upgrade path", true)
.Set("TargetImage/SourceFile", "target path", true);
You can also get their values in the same fashion (no casts).
string upgradeSource = wix.Get("PatchCreation/Family/UpgradeImage/SourceFile", string.Empty);
string targetSource = wix.Get("PatchCreation/Family/UpgradeImage/TargetImage/SourceFile", string.Empty);
Or this can be written as:
XElement upgradeImage = wix.GetElement("PatchCreation/Family/UpgradeImage");
string upgradeSource = upgradeImage.Get("SourceFile", string.Empty);
string targetSource = upgradeImage.Get("TargetImage/SourceFile", string.Empty);
To get a list of integers:
<root>
<path>
<list>
<value>1</value>
<value>12</value>
<value>13</value>
<value>14</value>
<value>15</value>
</list>
</path>
</root>
Use the GetEnumerable() method:
List<int> list = root
.GetEnumerable("path/list/value", xvalue => xvalue.Get(null, int.MinValue));
.ToList();
To set a new list of ints:
var list2 = new int[] { 1, 3, 4, 5, 6, 7, 8, 9, 0 };
root.SetEnumerable("path/list", list2, a => new XElement("value", a));
Which results in this new xml:
<root>
<path>
<list>
<value>1</value>
<value>3</value>
<value>4</value>
<value>5</value>
<value>6</value>
<value>7</value>
<value>8</value>
<value>9</value>
<value>0</value>
</list>
</path>
</root>

Your best bet is to use XmlSerialization. So serialize to XML and then deserialize to objects then you do not have to use casting.
Sometimes XML is created by another means other than serialization. Yet you can still create classes that represent your XML structure and deserialise.
For example:
Public Class Foo
{
public Range Range {get; set;}
}
public class Range
{
public int X {get; set;}
public int Y {get; set;}
}
Then you use this:
XmlSerializer ser = new XmlSerializer(typeof(Foo));

I frequently use an XSD to validate the XML structure, partially for this exact reason and since I don't have default constructors and/or have private fields, XMLSerialization is not often an option either.
If the XML validates without errors, then I go ahead and use Linq2Xml and use the various Parse(String s) methods to get data in the type my class requires, but I have not found a clean solution yet that will do this without any kind of conversion.
The validation steps avoids exceptions due to an incorrect data type.
var query = from tst in xml.Elements("test")
select new
{
int1 = Int32.Parse(tst.Element("int1").Value),
double1 = Double.Parse(tst.Element("double1").Value),
double2 = Double.Parse(tst.Element("double2").Value),
}
EDIT: Added info to respond to comment"
You can create an XSD directly from the Visual Studio GUI and there are other tools that do it too, but I generally just use Visual Studio. Open the XML in the editor, then from the XML menu, select "Create Schema" (path is shown in the snapshot).
The resulting XSD is very basic. It tried to go through and "guess" the appropriate data type for each node, and it does not include any additional restrictions, but it does a decent job of putting the framework together for you.
Once that is done, you can go in and tweak the data types to better fit your needs (if desired) and you can add your own restrictions to the data (such as requiring that an xs:int value be in a range of 0 and 50 or an xs:string value be less than 10 characters long - there are dozens of other possibilities, but that should give you the idea).
I actually just played around with the XSD language and it go progressively easier the more I did it. The W3Schools site was invaluable.

We use Linq To Xsd to create strongly types class wrappers around an XDocument.
You just write a schema file (Xsd) and include it in your project (once you've hacked LinqToXsd into the csproj file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Foo1">
<xs:complexType>
<xs:sequence>
<xs:element name="Range1">
<xs:complexType>
<xs:sequence>
<xs:element name="X" type="xs:int"/>
<xs:element name="Y" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then you can access classes of the same name:
Foo1 foo = new Foo1()
{
Range1 = new Foo1.Range1()
{
X = 7,
Y = 10,
}
};
foo.Save(foo.xml);
var input = Foo1.Load(input.xml);
Console.WriteLine(input.Range1.X.ToString());
J.

Related

How to parse a Generic XML File in C# to create a Table in SQL Server database

I have this Generic XML file, I want to parse it so I can create a SQL server table according to the XML data :
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Student">
<xs:complexType>
<xs:sequence>
<xs:element name="Id" type="xs:integer"/>
<xs:element name="Name" type="xs:string"/>
<xs:element name="City" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I want to recover the following data:
Student,
Id / integer
Name / String
City / String
Student will be the name of the table, and Id, Name and City are the columns. All I need is how to parse the XML file and recover the data.
Your XML file is an XML Schema Definition (XSD) file that formally describe[s] the elements in an Extensible Markup Language (XML) document. You can load such a file into an XmlSchemaSet schema collection, compile it, and then interrogate the schemas thereby defined to get your main element name and its properties.
Let's say that you have a string xsdString that contains the XSD shown in your question. Then you can load it, compile it, and print out the complex elements and their properties as follows:
// Load the xsdString into an XmlSchemaSet.
// If loading from a file use a StreamReader rather than a StringReader
XmlSchemaSet schemaSet = new XmlSchemaSet();
using (var reader = new StringReader(xsdString))
{
schemaSet.Add(XmlSchema.Read(reader, null));
}
// Compile the schema
schemaSet.Compile();
// Iterate over the schemas
// Code adapted from https://learn.microsoft.com/en-us/dotnet/standard/data/xml/traversing-xml-schemas
foreach (XmlSchema schema in schemaSet.Schemas())
{
// Iterate over the complex types in the schema
foreach (XmlSchemaElement element in schema.Elements.Values)
{
var complexType = element.ElementSchemaType as XmlSchemaComplexType;
if (complexType == null)
continue;
Console.WriteLine("Complex element: {0}", element.Name);
// If the complex type has any attributes, get an enumerator
// and write each attribute name to the console.
if (complexType.AttributeUses.Count > 0)
{
var enumerator = complexType.AttributeUses.GetEnumerator();
while (enumerator.MoveNext())
{
var attribute = (XmlSchemaAttribute)enumerator.Value;
var name = attribute.Name;
var type = attribute.AttributeSchemaType.TypeCode;
Console.WriteLine(" Attribute {0}: {1}", name, type);
}
}
// Get the sequence particle of the complex type.
var sequence = complexType.ContentTypeParticle as XmlSchemaSequence;
if (sequence != null)
{
// Iterate over each XmlSchemaElement in the Items collection.
foreach (XmlSchemaElement childElement in sequence.Items)
{
var name = childElement.Name;
var type = childElement.ElementSchemaType.TypeCode;
Console.WriteLine(" Element {0}: {1}", name, type);
}
}
}
}
Which outputs
Complex element: Student
Element Id: Integer
Element Name: String
Element City: String
Note that the XSD type xs:integer corresponds to an unbounded integer, not necessarily one that will fit in an Int32 or Int64.
References:
Traversing XML Schemas
How to parse an XSD to get the information from <xsd:simpleType> elements using C#?
XSD: What is the difference between xs:integer and xs:int?
Demo fiddle here.

Find duplicate elements based on another tag value XML

I have an extremely complicated XML and I need to check if a particular element exists only once inside each child of the XML.
<?xml version="1.0" encoding="UTF-8"?>
<deal>
<commercial>
<party />
<party>
<role_detail>
<role_type>Primary</role_type>
</role_detail>
<listingagents>
<listingagent>1</listingagent>
<listingagent>2</listingagent>
</listingagents>
</party>
<party>
<role_detail>
<role_type>Secondary</role_type>
</role_detail>
<listingagents>
<listingagent>1</listingagent>
</listingagents>
</party>
<party />
</commercial>
<commercial />
<commercial />
</deal>
Each commercial tag should contain only one listingagent tag when the party tag has role_type = PRIMARY.
For each commercial, I need to pick out party of type Primary and then check for listingagents tag and it should contain only one child listingagent.
Use XML Schema.xsd and limit your occurs:
For instance:
<xs:element name="listingagents" maxOccurs="unbounded" type="listingagentsType"/>
<xs:complexType name="listingagentsType">
<xs:sequence>
<xs:element name="listingagent" type="parameterType" maxOccurs="1"/>
</xs:sequence>
XElement xml = //...
bool xmlIsInvalid = xml.Elements("commercial")
.Select(c => c.Elements("party")
.Single(p => p.Element("role_detail").Element("role_type").Value == "Primary"))
.Any(p => p.Element("listingagents").Elements("listingagent").Count() > 1);
For every commercial element, get the single child party element whose role_type is Primary. Return true if any of these party elements contain more than 1 listingagentin listingagents.
Note this solution assumes a number of things about the structure of your XML - i.e. party will always have a child role_detail element, listingagents will always have at least one listingagent, etc.
I like querying XML nodes with XDocument (System.Xml.Linq). I would first find the invalid primary parties with more than 1 listing agent, and go from there...
XDocument doc = XDocument.Parse(File.ReadAllText("XMLFile1.xml"));
var allParties = doc.Descendants("commercial").Elements("party");
// invalid primary parties with more than 1 listing agent
var invalidPrimaries = allParties.Where(p => p.Element("role_detail")?.Value.ToUpper() == "PRIMARY" &&
p.Element("listingagents")?.Elements("listingagent").Count() > 1);
var validParties = allParties.Except(invalidPrimaries);
var validCommericals = validParties.Select(p => p.Parent).Distinct().ToList();

Obtain child node based on attribute of parent node

I have a CrystalReport report in XML (sorry for the verboseness, I cut out most sample data)
<?xml version="1.0" encoding="UTF-8" ?>
<FormattedReport xmlns = 'urn:crystal-reports:schemas' xmlns:xsi = 'http://www.w3.org/2000/10/XMLSchema-instance'>
<FormattedAreaPair Level="0" Type="Report">
<FormattedAreaPair Level="1" Type="Details">
<FormattedArea Type="Details">
<FormattedSections>
<FormattedSection SectionNumber="0">
<FormattedReportObjects>
<FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Tail Number}"><ObjectName>Field2</ObjectName>
<FormattedValue>C-FBCS</FormattedValue>
<Value>C-FBCS</Value>
</FormattedReportObject>
<FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Type ID}"><ObjectName>Field8</ObjectName>
<FormattedValue>DHC8</FormattedValue>
<Value>DHC8</Value>
</FormattedReportObject>
<FormattedReportObject xsi:type="CTFormattedField" Type="xsd:unsignedLong" FieldName="{TRIP LEGS.Trip Number}"><ObjectName>Field9</ObjectName>
<FormattedValue>68344</FormattedValue>
<Value>68344.00</Value>
</FormattedReportObject>
</FormattedReportObjects>
</FormattedSection>
</FormattedSections>
</FormattedArea>
</FormattedAreaPair>
<FormattedAreaPair Level="1" Type="Details">
<FormattedArea Type="Details">
<FormattedSections>
<FormattedSection SectionNumber="0">
<FormattedReportObjects>
<FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Tail Number}"><ObjectName>Field2</ObjectName>
<FormattedValue>C-FBCS</FormattedValue>
<Value>C-FBCS</Value>
</FormattedReportObject>
<FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Type ID}"><ObjectName>Field8</ObjectName>
<FormattedValue>DHC8</FormattedValue>
<Value>DHC8</Value>
</FormattedReportObject>
<FormattedReportObject xsi:type="CTFormattedField" Type="xsd:unsignedLong" FieldName="{TRIP LEGS.Trip Number}"><ObjectName>Field9</ObjectName>
<FormattedValue>68344</FormattedValue>
<Value>68344.00</Value>
</FormattedReportObject>
</FormattedReportObjects>
</FormattedSection>
</FormattedSections>
</FormattedArea>
</FormattedAreaPair>
...
</FormattedAreaPair>
</FormattedReport>
I am attempting to use a LINQ to XML query to extract the
Value node based on the parent node's FieldName attribute and place those into an object. There is no unique attribute for Value or the parents of FormattedReportObject nodes. So far here is my code to do so
from fs in xDoc.Descendants("FormattedSection")
select new FlightSchedule
{
AircraftType = from fos in fs.Descendants("FormattedReportObjects")
from fo in fs.Descendants("FormattedReportObject")
where fo.Attribute("FieldName").Value.Equals("{AIRCRAFT.Type ID}")
from e in fo.Element("Value")
select e.Value),
....
};
I keep getting errors:
An expression of type 'System.Xml.Linq.XElement' is not allowed in a subsequent from clause in a query expression with source type 'System.Collections.Generic.IEnumerable'. Type inference failed in the call to 'SelectMany')
or if I don't get an error I end up retrieving nothing. Any suggestions would be greatly appreciated on improving my query.
Your code has several problems. First, the thing the compiler is complaining about is, as #MizardX mentioned, that you are using fo.Element("Value") as if it was a sequence. What you probably want is to write let e = fo.Element("Value") (or skip this part completely and directly write select fo.Element("Value").Value).
Another problem is that your XML is using a namespace, but you aren't. This means that you should create a XNamespace object and use it wherever you have element names.
Also, the way your code is written, AircraftType is a sequence of strings. I assume this is not what you wanted.
And seeing that you want to do the same thing for different values of FieldName, you probably want to make this into a method.
With all the problems mentioned above fixed, the code should look something like this:
static readonly XNamespace ns = XNamespace.Get("urn:crystal-reports:schemas");
string GetFieldValue(XElement fs, string fieldName)
{
return (from fo in fs.Descendants(ns + "FormattedReportObject")
where fo.Attribute("FieldName").Value == fieldName
let e = fo.Element(ns + "Value")
select e.Value).Single();
}
…
var flts = (from fs in xDoc.Descendants(ns + "FormattedSection")
select new FlightSchedule
{
AircraftType = GetFieldValue(fs, "{AIRCRAFT.Type ID}"),
…
}).ToList();
fo.Element("Value") returns an XElement-object. What you want is probably fo.Elements("Value") (note the plural 's').
The error message was complaining that it didn't know how to iterate over the XElement object.
The reason you are not getting any results, is that the XML-file is using namespaces. To find elements outside the default namespace, you need to prefix the namespace before the node name.
I also noticed that you are not using the fos variable, so that loop is unnecessary. fs.Decendants() is already giving you the correct result.
List<FlightSchedule> flts =
(from fs in xDoc.Descendants("{urn:crystal-reports:schemas}FormattedSection")
select new FlightSchedule
{
AircraftType =
(from fo in fs.Descendants("{urn:crystal-reports:schemas}FormattedReportObject")
where fo.Attribute("FieldName").Value == "{AIRCRAFT.Type ID}"
from e in fo.Elements("{urn:crystal-reports:schemas}Value")
select e.Value),
....
}).ToList();

How do I write a Lambda statement for this Linq to XML function?

I am working with this XSD file. The portion of the XML that is relevant to this question is here:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="https://wsmrc2vger.wsmr.army.mil/rcc/manuals/106-11"
targetNamespace="https://wsmrc2vger.wsmr.army.mil/rcc/manuals/106-11"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="Tmats">
<xs:complexType>
<xs:sequence>
<xs:annotation>
<xs:documentation>TMATS G Group</xs:documentation>
</xs:annotation>
<xs:element name="ProgramName" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>PN</xs:documentation>
</xs:annotation>
</xs:element>
To get the documentation value for a given xs:element, I have this small function, which recursively walks the descendant nodes until it finds the documentation element:
public string GetCode(XElement e)
{
foreach (var s in e.Elements())
{
// If we hit an intervening element, bail out.
if (s.Name.ToString().Contains("element"))
return "";
if (s.Name.ToString().Contains("annotation"))
{
// I'll explain this loop in a moment.
foreach (var t in s.Elements())
{
if (t.Name.ToString().Contains("documentation"))
return t.Value;
}
}
else
return GetCode(s);
}
return "";
}
So far so good. The unit test looks like this:
[TestMethod()]
public void GetCodeTest()
{
string path = #"C:\Documents and Settings\harvey robert\Desktop\Tmats.xsd";
IEnumerable<XElement> elements =
from e in XElement.Load(path).Elements()
select e;
TmatsDictionary target = new TmatsDictionary();
XElement x = elements.First();
string actual = target.GetCode(x);
Assert.AreEqual("TMATS G Group", actual);
}
Which passes. Now I want to extend the test by adding an additional case, like this:
XElement z = elements.DescendantsAndSelf()
.First(y => y.Attribute("name")
.ToString().Contains("ProgramName"));
actual = target.GetCode(z);
Assert.AreEqual("PN", actual);
...But this fails due to a null object reference (most likely y.Attribute("name")).
Did you see the loop in the function above that I commented?
// I'll explain this loop in a moment.
foreach (var t in s.Elements())
{
if (t.Name.ToString().Contains("documentation"))
return t.Value;
}
It's written that way because I can't figure out how to express the condition in a Lambda statement that works.
Any suggestions?
You need to use namespaces:
XNamespace ns = "https://wsmrc2vger.wsmr.army.mil/rcc/manuals/106-11";
XElement z = elements.DescendantsAndSelf()
.First(y => y.Attribute(ns + "name")
.Value.Contains("ProgramName"));
Try this
elements.DescendantsAndSelf().
First(y => y.Attribute(XName.Get("name", "http://www.w3.org/2001/XMLSchema")));
Your problem is that y.Attribute("name").ToString().Contains("ProgramName") will fail on every element that doesn't contain a "name" attribute. You need something like this:
y.Attribute("name") != null &&
y.Attribute("name").ToString().Contains("ProgramName");
If you expect all <element> elements to contain a name attribute, you can ignore the null check and do this:
XElement z = elements.DescendantsAndSelf(
"{http://www.w3.org/2001/XMLSchema}element")
.First(y => y.Attribute("name")
.ToString().Contains("ProgramName"));
EDIT: Note that I added the expanded name to include the namespace URL. See if that works.
Here is the code that works.
Notice the call to the GetName() method in the DescendantsAndSelf() call. This returns a properly formatted URI-prefixed name of the form {http://www.w3.org/2001/XMLSchema}element, which will match correctly to the xs:element names.
The result is that DescendantsAndSelf() returns only those elements having the name xs:element, all of which have attributes associated with them (so there is no chance of a null reference error when referencing the Attributes collection).
[TestMethod()]
public void GetCodeTest()
{
string path = #"C:\TestArea\Tmats_09-2010.xml";
IEnumerable<XElement> elements =
from e in XElement.Load(path).Elements()
select e;
TmatsDictionary target = new TmatsDictionary();
XNamespace ns = "http://www.w3.org/2001/XMLSchema";
XElement z = elements.DescendantsAndSelf(ns.GetName("element"))
.First(y => y.Attribute("name")
.Value.Equals("ProgramName"));
actual = target.GetCode(z);
Assert.AreEqual("PN", actual);
}

Read typed objects from XML using known XSD

I have the following (as an example) XML file and XSD.
<?xml version="1.0" encoding="utf-8" ?>
<foo>
<DateVal>2010-02-18T01:02:03</DateVal>
<TimeVal>PT10H5M3S</TimeVal>
</foo>
and
version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="foo">
<xs:complexType>
<xs:sequence>
<xs:element name="DateVal" type="xs:dateTime" />
<xs:element name="TimeVal" type="xs:duration" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then the following C# code:
static void Main(string[] args)
{
XmlDocument xd = new XmlDocument();
XmlSchema xs;
using (var fs = File.OpenRead(FilePath + "SimpleFields.xsd"))
{
xs = XmlSchema.Read(fs, null);
}
xd.Schemas.Add(xs);
xd.Load((FilePath + "SimpleFields.xml"));
xd.Validate(null);
var el_root = xd.DocumentElement;
var el_date = (XmlElement)el_root.SelectSingleNode("./DateVal");
//WANTED: el_date.Value = 2010-02-18 01:02:03 (as a DateTime Object)
//ACTUAL: el_date.InnerText="2010-02-18T01:02:03"
var el_duration = (XmlElement)el_root.SelectSingleNode("./TimeVal");
//WANTED: el_date.Value = 10 hours, 5 minutes, 3 seconds (as a TimeSpan Object)
//ACTUAL: el_date.InnerText="PT10H5M3S"
Console.WriteLine("DONE");
Console.ReadLine();
}
How can I read the data as strongly typed objects ?
I will be targetting a WindowsMobile device, but this shouldn't need to affect the answer too much. (can be .NET 2.0 or 3.5 ... Not sure if Sstem.Xml.Linq will help or not)
You need to do two steps:
1) Take your XML schema file and run it through the xsd.exe utility (which comes with the Windows SDK - it's in C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ or some similar path. This can turn the XSD file into a C# class:
xsd /c yourfile.xsd
This should give you a file yourfile.cs which contains a class representing that XML schema.
2) Now, armed with that C# class, you should be able to just deserializing the XML file into an instance of your new object:
XmlSerializer ser = new XmlSerializer(typeof(foo));
string filename = Path.Combine(FilePath, "SimpleFields.xml");
foo myFoo = ser.Deserialize(new FileStream(filename, FileMode.Open)) as foo;
if (myFoo != null)
{
// do whatever you want with your "foo"
}
That's about as simple as it gets! :-)
OK - Found the answer I was looking for.
it is the XmlConvert class.
var el_date = (XmlElement)el_root.SelectSingleNode("./DateVal");
//WANTED: el_date.Value = 2010-02-18 01:02:03 (as a DateTime Object)
var val_date = XmlConvert.ToDateTime(el_date.InnerText);
//ACTUAL: el_date.InnerText="2010-02-18T01:02:03"
var el_duration = (XmlElement)el_root.SelectSingleNode("./TimeVal");
//WANTED: el_date.Value = 10 hours, 5 minutes, 3 seconds (as a TimeSpan Object)
var val_duration = XmlConvert.ToTimeSpan(el_duration.InnerText);
//ACTUAL: el_date.InnerText="PT10H5M3S"
Marc's answer was correct in terms of reading in a whole strongly-typed class, but in this case I only wanted to read a single strongly-typed element/node.

Categories