I am new to c# and XML deserialization, pardon me for any wrong words/mising any information.
I am deserializing a Nunit3 test result XML with root element as test-run and child elements are test-suite and then test-case.
test-case is repeated multiple times depending on number of test cases executed and also the element which I am interested in.
The C# class for the Nunit XML is like the following.
[XmlRoot(ElementName = "test-run")]
public class Testrun
{
[XmlElement(ElementName = "command-line")]
public string Commandline { get; set; }
[XmlElement(ElementName = "test-suite")]
public Testsuite Testsuite { get; set; }
}
[XmlRoot(ElementName = "test-suite")]
public class Testsuite
{
[XmlElement(ElementName = "test-case")]
public Testcase Testcase { get; set; }
}
But sometimes nested test-suite element occurs in Nunit XML as following.
<test-suite type="TestSuite" id="0-1005" name="TopGearFramework" fullname="TopGearFramework" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.354384" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestSuite" id="0-1006" name="CFTestCases" fullname="TopGearFramework.CFTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.353019" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestSuite" id="0-1007" name="PoCTestCases" fullname="TopGearFramework.CFTestCases.PoCTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352989" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestSuite" id="0-1008" name="FeatureFiles" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352968" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestFixture" id="0-1002" name="IndividualDealerPartyCreationFeature" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" testcasecount="1" result="Passed" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:07Z" duration="99.414157" total="1" passed="1" failed="0" warnings="0" inconclusive="0" skipped="0" asserts="10">
<test-case id="0-1003" name="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature.XF_PAM_004_CheckNewDealerPartyCreationForIndividual" methodname="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" seed="293675085" result="Passed" start-time="2019-02-21 04:17:29Z" end-time="2019-02-21 04:19:07Z" duration="98.585096" asserts="10">
Note that the test-suite is repeated 5 times before test-case occurs. With this during deserialization, I am getting null to test-case object.
How to handle the dynamic nesting or repetition of test-suite element to get the test-case?
Thanks in advance.
Edit 1# Full XML copied for reference.
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<test-run id="2" testcasecount="2" result="Failed" total="2" passed="1" failed="1" inconclusive="0" skipped="0" asserts="14" engine-version="3.9.0.0" clr-version="4.0.30319.42000" start-time="2019-02-21 04:17:25Z" end-time="2019-02-21 04:19:16Z" duration="111.183778">
<command-line><![CDATA["C:\Program Files (x86)\NUnit.org\nunit-console\nunit3-console.exe" TopGearFramework\bin\Debug\TopGearFramework.dll --result=TestResult.xml --labels=All --out=TestResult.txt]]></command-line>
<test-suite type="Assembly" id="0-1004" name="TopGearFramework.dll" fullname="TopGearFramework.dll" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.409138" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<environment framework-version="3.11.0.0" clr-version="4.0.30319.42000" os-version="Microsoft Windows NT 10.0.16299.0" platform="Win32NT" cwd="C:\Users\qxm5789\.jenkins\workspace\TopGearTestRunner_master" machine-name="VMUC0034748" user="qxm5789" user-domain="MUC" culture="en-US" uiculture="en-US" os-architecture="x64" />
<settings>
<setting name="DisposeRunners" value="True" />
</settings>
<properties>
<property name="_PID" value="1852" />
<property name="_APPDOMAIN" value="domain-" />
</properties>
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1005" name="TopGearFramework" fullname="TopGearFramework" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.354384" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1006" name="CFTestCases" fullname="TopGearFramework.CFTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.353019" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1007" name="PoCTestCases" fullname="TopGearFramework.CFTestCases.PoCTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352989" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1008" name="FeatureFiles" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352968" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestFixture" id="0-1002" name="IndividualDealerPartyCreationFeature" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" testcasecount="1" result="Passed" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:07Z" duration="99.414157" total="1" passed="1" failed="0" warnings="0" inconclusive="0" skipped="0" asserts="10">
<properties>
<property name="Description" value="Individual Dealer Party Creation" />
</properties>
<output><![CDATA[-> Using app.config
]]></output>
<test-case id="0-1003" name="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature.XF_PAM_004_CheckNewDealerPartyCreationForIndividual" methodname="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" seed="293675085" result="Passed" start-time="2019-02-21 04:17:29Z" end-time="2019-02-21 04:19:07Z" duration="98.585096" asserts="10">
<properties>
<property name="Description" value="XF_PAM_004_Check New Dealer Party Creation for Individual" />
</properties>
<output><![CDATA[Given Browser is launched
-> done: IndividualDealerPartyCreationSteps.GivenBrowserIsLaunched() (0.0s)
]]></output>
<attachments>
<attachment>
<filePath>C:\Users\qxm5789\.jenkins\workspace\TopGearTestRunner_master\TestResults\\XF_PAM_004_Check New Dealer Party Creation for Individual2019-02-21-11_19_02.jpg</filePath>
<description><![CDATA[Screenshot captured]]></description>
</attachment>
</attachments>
</test-case>
</test-suite>
<test-suite type="TestFixture" id="0-1000" name="TestOriginationAPIFeature" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature" runstate="Runnable" testcasecount="1" result="Failed" site="Child" start-time="2019-02-21 04:19:07Z" end-time="2019-02-21 04:19:16Z" duration="8.923635" total="1" passed="0" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="4">
<properties>
<property name="Description" value="Test Origination API" />
</properties>
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-case id="0-1001" name="FE_AHA_040_SearchApplicationByApplicationIDThroughOriginationAPI" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature.FE_AHA_040_SearchApplicationByApplicationIDThroughOriginationAPI" methodname="FE_AHA_040_SearchApplicationByApplicationIDThroughOriginationAPI" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature" runstate="Runnable" seed="2107869277" result="Failed" start-time="2019-02-21 04:19:07Z" end-time="2019-02-21 04:19:16Z" duration="8.921560" asserts="4">
<properties>
<property name="Description" value="FE_AHA_040_Search Application By Application ID through Origination API" />
</properties>
<failure>
<message><![CDATA[ Error Occured:
Expected: <empty>
But was: < "Contract ID 12345 not found." >
]]></message>
<stack-trace><![CDATA[
]]></stack-trace>
</failure>
<output><![CDATA[
]]></output>
<assertions>
<assertion result="Failed">
<message><![CDATA[ Error Occured:
Expected: <empty>
But was: < "Contract ID 12345 not found." >
]]></message>
<stack-trace><![CDATA[
]]></stack-trace>
</assertion>
</assertions>
</test-case>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-run>
If you want to get all <test-case> nodes in any depth in XML then XDocument.Descendants("test-case") will do this for you.
And by using LINQ you can retrieve attribute result from each <test-case> node and message from <failure> node if present inside <test-case> node.
Then below code gives you a list of failure message with the result.
class Program
{
public static void Main(string[] args)
{
XDocument doc = XDocument.Load(#"Path to your xml file");
var result = (from t in doc.Descendants("test-case")
from f in t.Descendants("failure")
select new
{
Result = t.Attribute("result").Value,
Failure_Message = f.Element("message") != null ? f.Element("message").Value : ""
}).ToList();
//---------------Print the result------------------
foreach (var item in result)
{
Console.WriteLine("Result: " + item.Result);
Console.WriteLine("Message: " + item.Failure_Message);
}
Console.ReadLine();
}
Output:
You need a custom parser. I used xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication100
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Testrun testrun = new Testrun();
testrun.ParseXml(FILENAME);
}
}
public class Testrun
{
public string Commandline { get; set; }
public Testsuite Testsuite { get; set; }
public void ParseXml(string filename)
{
XDocument doc = XDocument.Load(filename);
XElement Testrun = doc.Root;
Commandline = (string)Testrun.Element("command-line");
XElement testsuit = Testrun.Element("test-suite");
if (testsuit != null)
{
Testsuite = new Testsuite(testsuit);
}
}
}
public class Testsuite
{
public Attributes attributes { get; set; }
public Testsuite testsuite { get; set; }
public string failure_message { get; set; }
public string property_name { get; set; }
public string property_value { get; set; }
public TestCase TestCase { get; set; }
public Testsuite(XElement xTestsuite)
{
attributes = new Attributes(xTestsuite);
XElement failure = xTestsuite.Element("failure");
if (failure != null) failure_message = (string)failure.Element("message");
XElement properties = xTestsuite.Element("properties");
if (properties != null)
{
XElement property = properties.Element("property");
property_name = (string)property.Attribute("name");
property_value = (string)property.Attribute("value");
}
XElement testcase = xTestsuite.Element("test-case");
if (testcase != null)
{
TestCase = new TestCase(testcase);
}
xTestsuite = xTestsuite.Element("test-suite");
if (xTestsuite != null)
{
testsuite = new Testsuite(xTestsuite);
}
}
}
public class TestCase
{
public string output { get; set; }
public string property_name { get; set; }
public string property_value { get; set; }
public string attachment_filePath { get; set; }
public string attachment_description { get; set; }
public TestCase(XElement testCase)
{
XElement xOutput = testCase.Element("output");
if (xOutput != null) output = (string)xOutput;
XElement properties = testCase.Element("properties");
if (properties != null)
{
XElement property = properties.Element("property");
property_name = (string)property.Attribute("name");
property_value = (string)property.Attribute("value");
}
XElement attachments = testCase.Element("attachments");
if (attachments != null)
{
XElement attachment = attachments.Element("attachment");
attachment_filePath = (string)attachment.Element("filePath");
attachment_description = (string)attachment.Element ("description");
}
}
}
public class Attributes
{
string testtype { get; set; }
string id { get; set; }
string name { get; set; }
string fullname { get; set; }
string runstate { get; set; }
int testcasecount { get; set; }
string result { get; set; }
string site { get; set; }
DateTime start_time { get; set; }
DateTime end_time { get; set; }
decimal duration { get; set; }
int total { get; set; }
int passed { get; set; }
int failed { get; set; }
int warnings { get; set; }
int inconclusive { get; set; }
int skipped { get; set; }
int asserts { get; set; }
public Attributes(XElement attributes)
{
testtype = (string)attributes.Attribute("type");
id = (string)attributes.Attribute("id");
name = (string)attributes.Attribute("name");
fullname = (string)attributes.Attribute("fullname");
runstate = (string)attributes.Attribute("runstate");
testcasecount = (int)attributes.Attribute("testcasecount");
result = (string)attributes.Attribute("result");
site = (string)attributes.Attribute("site");
start_time = (DateTime)attributes.Attribute("start-time");
end_time = (DateTime)attributes.Attribute("end-time");
duration = (decimal)attributes.Attribute("duration");
total = (int)attributes.Attribute("total");
passed = (int)attributes.Attribute("passed");
failed = (int)attributes.Attribute("failed");
warnings = (int)attributes.Attribute("warnings");
inconclusive = (int)attributes.Attribute("inconclusive");
skipped = (int)attributes.Attribute("skipped");
asserts = (int)attributes.Attribute("asserts");
}
}
}
Related
Many Thanks in advance for any help in creating a class and deserializing xml file like below in .NET
example of xml data
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<Article>
<Story>
<Title>Some Title 1</Title>
<Author>John</Author>
<Lead>Some Lead 1</Lead>
<Subtitle>SubTitle 1-1</Subtitle>
<Body>body 1-1-1</Body>
<Body>body 1-1-2</Body>
<Body>body 1-1-3</Body>
<Body>body 1-1-4</Body>
<Subtitle>SubTitle 1-2</Subtitle>
<Body>body 1-2-1</Body>
<Body>body 1-2-2</Body>
<Subtitle>SubTitle 1-3</Subtitle>
<Body>body 1-3-1</Body>
<Body>body 1-3-2</Body>
<Body>body 1-3-3</Body>
</Story>
<Story>
<Title>Some Title 2</Title>
<Author>Adam</Author>
<Lead>Some Lead 2</Lead>
<Subtitle>SubTitle 2-1</Subtitle>
<Body>body 2-1-1</Body>
<Body>body 2-1-2</Body>
<Body>body 2-1-3</Body>
<Subtitle>SubTitle 2-2</Subtitle>
<Body>body 2-2-1</Body>
<Body>body 2-2-2</Body>
<Subtitle>SubTitle 2-3</Subtitle>
<Body>body 2-3-1</Body>
</Story>
<Story>
<Picture>
<Image href="someFile1.jpg"></Image>
<Credit>Credit 1</Credit>
<Description>Description Image 1</Description>
</Picture>
</Story>
<Story>
<Picture>
<Image href="someFile2.jpg"></Image>
<Credit>Credit 2</Credit>
</Picture>
</Story>
</Article>
</Root>
I have prepared Domain class for like this (but maybe it's not the best idea for my xml file)
using System.Collections.Generic;
using System.Xml.Serialization;
namespace QgeImagingXmlConnector.Domain
{
[XmlRoot(ElementName = "Root")]
public class InputXmlModel
{
[XmlElement("Article")]
public List<Article> Articles { get; set; }
}
public class Article
{
[XmlElement("Story")]
public List<Story> Stories { get; set; }
}
public class Story
{
public string Title { get; set; }
public string Author { get; set; }
public string Lead { get; set; }
public List<Item> Items { get; set; }
//OR
public List<StoryPicture> Pictures { get; set; }
}
public class StoryPicture
{
public string ImageHref { get; set; }
public string Credit { get; set; }
public string Description { get; set; }
}
public class Item
{
public string ItemType { get; set; } // Possible: Body or Subtitle
public string ItemText { get; set; }
}
}
and method for deserialize
public InputXmlModel GetInputXmlModelByXmlFile(string filePath)
{
XmlSerializer serializer = new XmlSerializer(typeof(InputXmlModel));
TextReader tr = new StreamReader(filePath);
var result = (InputXmlModel)serializer.Deserialize(tr);
tr.Close();
return result;
}
And my question is: How to change my class to work ( by adding some attributes or change structure )
STORY could by like Story with some content or Story with only picture
so in my class i added 2 classes Story and StoryPicture
In Content of Story we can have many body or subtitle tags - but the order is important
Regards
P.S.
this is what i want to get as an result
I put data only for first Story
var result = new InputXmlModel
{
Articles = new List<Article>
{
{
new Article
{
Stories = new List<Story>
{
{new Story
{
Title = "Some Title 1",
Author = "John",
Lead="Some Lead 1",
Items = new List<Item>
{
new Item{ItemType = "Subtitle", ItemText = "SubTitle 1-1"},
new Item{ItemType = "Body", ItemText = "body 1-1-1"},
new Item{ItemType = "Body", ItemText = "body 1-1-2"},
new Item{ItemType = "Body", ItemText = "body 1-1-3"},
new Item{ItemType = "Body", ItemText = "body 1-1-4"},
new Item{ItemType = "Subtitle", ItemText = "SubTitle 1-2"},
new Item{ItemType = "Body", ItemText = "body 1-2-1"},
new Item{ItemType = "Body", ItemText = "body 1-2-2"},
new Item{ItemType = "Subtitle", ItemText = "SubTitle 1-3"},
new Item{ItemType = "Body", ItemText = "body 1-3-1"},
new Item{ItemType = "Body", ItemText = "body 1-3-2"},
new Item{ItemType = "Body", ItemText = "body 1-3-3"},
}
}
}
// here next 3 stories ( one with Items, two for pictures )
}
}
}
}
};
Yes you can do this too like this.
Your model class would like:
using System.Collections.Generic;
using System.Xml.Serialization;
namespace QgeImagingXmlConnector.Domain
{
[XmlRoot(ElementName = "Root")]
public class InputXmlModel
{
[XmlElement("Article")]
public List<Article> Articles { get; set; }
}
public class Article
{
[XmlElement("Story")]
public List<Story> Stories { get; set; }
}
public class Story
{
public string Title { get; set; }
public string Author { get; set; }
public string Lead { get; set; }
[XmlElement("Item")]
public List<Item> Items { get; set; }
[XmlElement("Picture")]
public List<StoryPicture> Pictures { get; set; }
}
public class StoryPicture
{
public string ImageHref { get; set; }
public string Credit { get; set; }
public string Description { get; set; }
}
public class Item
{
public string ItemType { get; set; } // Possible: Body or Subtitle
public string ItemText { get; set; }
}
}
And your XML like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<Article>
<Story>
<Title>Some Title 1</Title>
<Author>John</Author>
<Lead>Some Lead 1</Lead>
<Subtitle>SubTitle 1-1</Subtitle>
<Body>body 1-1-1</Body>
<Body>body 1-1-2</Body>
<Body>body 1-1-3</Body>
<Body>body 1-1-4</Body>
<Subtitle>SubTitle 1-2</Subtitle>
<Body>body 1-2-1</Body>
<Body>body 1-2-2</Body>
<Subtitle>SubTitle 1-3</Subtitle>
<Body>body 1-3-1</Body>
<Body>body 1-3-2</Body>
<Body>body 1-3-3</Body>
</Story>
<Story>
<Title>Some Title 2</Title>
<Author>Adam</Author>
<Lead>Some Lead 2</Lead>
<Subtitle>SubTitle 2-1</Subtitle>
<Body>body 2-1-1</Body>
<Body>body 2-1-2</Body>
<Body>body 2-1-3</Body>
<Subtitle>SubTitle 2-2</Subtitle>
<Body>body 2-2-1</Body>
<Body>body 2-2-2</Body>
<Subtitle>SubTitle 2-3</Subtitle>
<Body>body 2-3-1</Body>
<Picture>
<Image href="someFile1.jpg"></Image>
<Credit>Credit 1</Credit>
<Description>Description Image 1</Description>
</Picture>
<Picture>
<Image href="someFile2.jpg"></Image>
<Credit>Credit 2</Credit>
</Picture>
</Story>
</Article>
</Root>
Is that what you're looking for?
Try following xml linq :
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication100
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Article article = doc.Descendants("Article").Select(x => new Article() { Stories = x.Elements("Story").Select(y => Story.ParseStory(y)).ToList() }).FirstOrDefault();
}
}
public class InputXmlModel
{
public List<Article> Articles { get; set; }
}
public class Article
{
public List<Story> Stories { get; set; }
}
public class Story
{
public string Title { get; set; }
public string Author { get; set; }
public string Lead { get; set; }
public List<Item> Items { get; set; }
public List<StoryPicture> Pictures { get; set; }
enum State
{
DEFAULT,
SUBTITLE,
}
public static Story ParseStory(XElement xStory)
{
Story story = new Story();
State state = State.DEFAULT;
Item newItem = null;
StoryPicture newPicture = null;
foreach (XElement child in xStory.Elements())
{
switch(state)
{
case State.DEFAULT :
switch (child.Name.LocalName)
{
case "Title" :
story.Title = (string)child;
break;
case "Author":
story.Author = (string)child;
break;
case "Lead":
story.Lead = (string)child;
break;
case "Subtitle":
newItem = new Item();
if (story.Items == null) story.Items = new List<Item>();
story.Items.Add(newItem);
state = State.SUBTITLE;
break;
case "Picture":
newPicture = new StoryPicture()
{
ImageHref = (string)child.Element("Image").Attribute("href"),
Credit = (string)child.Element("Credit"),
Description = (string)child.Element("Description")
};
if (story.Pictures == null) story.Pictures = new List<StoryPicture>();
story.Pictures.Add(newPicture);
break;
default:
Console.WriteLine("Error");
Console.ReadLine();
break;
}
break;
case State.SUBTITLE :
switch (child.Name.LocalName)
{
case "Body" :
newItem.ItemType = "SubTitle";
newItem.ItemText = (string)child;
break;
case "Subtitle":
newItem = new Item();
if (story.Items == null) story.Items = new List<Item>();
story.Items.Add(newItem);
break;
default:
Console.WriteLine("Error");
Console.ReadLine();
break;
}
break;
}
}
return story;
}
}
public class StoryPicture
{
public string ImageHref { get; set; }
public string Credit { get; set; }
public string Description { get; set; }
}
public class Item
{
public string ItemType { get; set; } // Possible: Body or Subtitle
public string ItemText { get; set; }
}
}
If you take out the <Root> tag in your XML and change your method for the deserialization to:
public InputXmlModel GetInputXmlModelByXmlFile(string filePath)
{
XmlSerializer serializer = new XmlSerializer(typeof(Article));
using (FileStream fileStream = new FileStream("<PathToFile>", FileMode.Open))
{
Article result = (Article)serializer.Deserialize(fileStream);
}
}
It should work.
I have the following class which I'm trying to serialize. And I have two arrays with the same data type. I know that if we need more than one element to have the same name the namespace has be different. But there a workaround to remove those namespaces altogether.
[XmlRoot]
public class Album
{
public string Title { get; set; }
public string Description { get; set;}
public int CoverImgIndx { get; set; }
[XmlElement(ElementName ="Element", Namespace ="www.image.com")]
public Image[] Images { get; set; }
[XmlElement(ElementName ="Element", Namespace ="www.cover.com")]
public Image[] Cover { get; set; }
}
public class Image
{
public int indx { get; set; }
public string filepath { get; set; }
}
And I'm using XmlSerializer to serialize this.
public class Program
{
public static void Main()
{
var album = new Album
{
Title = "Album Title",
Description = "Some explanation.",
CoverImgIndx = 2,
Images = new Image[] {
new Image { indx = 0, filepath = #"C:\Images\file1.jpg" },
new Image { indx = 1, filepath = #"C:\Images\file2.png" },
new Image { indx = 2, filepath = #"C:\Images\file3.jpg" }
},
Cover = new Image[] {
new Image { indx = 0, filepath = #"C:\Images\cover1.jpg" }
}
};
XmlSerializer serializer = new XmlSerializer(typeof(Album));
serializer.Serialize(Console.Out, album);
}
}
The output i'm getting there is a namespace for image element. is there way to remove namespace without having to remove Images and Cover shareing the same element name.
<?xml version="1.0" encoding="utf-16"?>
<Album xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Title>Album Title</Title>
<Description>Some explanation.</Description>
<CoverImgIndx>2</CoverImgIndx>
<Element xmlns="www.image.com">
<indx>0</indx>
<filepath>C:\Images\file1.jpg</filepath>
</Element>
<Element xmlns="www.image.com">
<indx>1</indx>
<filepath>C:\Images\file2.png</filepath>
</Element>
<Element xmlns="www.image.com">
<indx>2</indx>
<filepath>C:\Images\file3.jpg</filepath>
</Element>
<Element xmlns="www.cover.com">
<indx>0</indx>
<filepath>C:\Images\cover1.jpg</filepath>
</Element>
</Album>
The output i'm looking for
<?xml version="1.0" encoding="utf-16"?>
<Album xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Title>Album Title</Title>
<Description>Some explanation.</Description>
<CoverImgIndx>2</CoverImgIndx>
<Element>
<indx>0</indx>
<filepath>C:\Images\file1.jpg</filepath>
</Element>
<Element>
<indx>1</indx>
<filepath>C:\Images\file2.png</filepath>
</Element>
<Element>
<indx>2</indx>
<filepath>C:\Images\file3.jpg</filepath>
</Element>
<Element>
<indx>0</indx>
<filepath>C:\Images\cover1.jpg</filepath>
</Element>
</Album>
I need to figure out how to rename elements and/or attributes in generated XML using values retrieved from the database as my element names.
For instance, here is a potential XML output from my current process:
<ArrayOfEntityTreeBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EntityTreeBase EntityInfo="User">
<Children>
<EntityTreeBase EntityInfo="User Medication">
<Properties>
<EntityProperty CreatedDate="2013-11-14T16:41:12.75">
<FieldName>Medication Name</FieldName>
<Value>Celebrex</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-12-04T14:08:58.597">
<FieldName>Medication Dosage</FieldName>
<Value>20000MG</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-14T16:41:12.76">
<FieldName>Medication Prescribed Date</FieldName>
<Value>08/01/2013</Value>
</EntityProperty>
</Properties>
</EntityTreeBase>
<EntityTreeBase EntityInfo="User Medication">
<Properties>
<EntityProperty CreatedDate="2013-11-14T16:41:12.767">
<FieldName>Medication Name</FieldName>
<Value>Aspirin</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-14T16:41:12.77">
<FieldName>Medication Dosage</FieldName>
<Value>5 mg</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-14T16:41:12.78">
<FieldName>Medication Prescribed Date</FieldName>
<Value>09/01/2013</Value>
</EntityProperty>
</Properties>
</EntityTreeBase>
<EntityTreeBase EntityInfo="User Medication">
<Properties>
<EntityProperty CreatedDate="2013-11-14T16:41:12.783">
<FieldName>Medication Name</FieldName>
<Value>Celebrex</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-14T16:41:12.793">
<FieldName>Medication Dosage</FieldName>
<Value>50 mg twice a day</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-14T16:41:12.8">
<FieldName>Medication Prescribed Date</FieldName>
<Value>10/01/2013</Value>
</EntityProperty>
</Properties>
</EntityTreeBase>
</Children>
<Properties>
<EntityProperty CreatedDate="2013-12-03T13:48:03.45">
<FieldName>User First Name</FieldName>
<Value>John</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-12-03T11:36:31.423">
<FieldName>User MI</FieldName>
<Value>Q</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-19T09:56:44.66">
<FieldName>User Last Name</FieldName>
<Value>Public</Value>
</EntityProperty>
<EntityProperty CreatedDate="2013-11-14T16:41:12.803">
<FieldName>User SSN</FieldName>
<Value>111-22-3333</Value>
</EntityProperty>
</Properties>
</EntityTreeBase>
</ArrayOfEntityTreeBase>
What I need to accomplish is this:
<UserInformation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<User>
<UserMedications>
<UserMedication>
<MedicationProperties>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.75">
<FieldName>Medication Name</FieldName>
<Value>Celebrex</Value>
</MedicationProperty>
<MedicationProperty CreatedDate="2013-12-04T14:08:58.597">
<FieldName>Medication Dosage</FieldName>
<Value>20000MG</Value>
</MedicationProperty>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.76">
<FieldName>Medication Prescribed Date</FieldName>
<Value>08/01/2013</Value>
</MedicationProperty>
</MedicationProperties>
</UserMedication>
<UserMedication>
<MedicationProperties>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.767">
<FieldName>Medication Name</FieldName>
<Value>Aspirin</Value>
</MedicationProperty>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.77">
<FieldName>Medication Dosage</FieldName>
<Value>5 mg</Value>
</MedicationProperty>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.78">
<FieldName>Medication Prescribed Date</FieldName>
<Value>09/01/2013</Value>
</MedicationProperty>
</MedicationProperties>
</UserMedication>
<UserMedication>
<MedicationProperties>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.783">
<FieldName>Medication Name</FieldName>
<Value>Celebrex</Value>
</MedicationProperty>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.793">
<FieldName>Medication Dosage</FieldName>
<Value>50 mg twice a day</Value>
</MedicationProperty>
<MedicationProperty CreatedDate="2013-11-14T16:41:12.8">
<FieldName>Medication Prescribed Date</FieldName>
<Value>10/01/2013</Value>
</MedicationProperty>
</MedicationProperties>
</UserMedication>
</UserMedications>
<UserProperties>
<UserProperty CreatedDate="2013-12-03T13:48:03.45">
<FieldName>User First Name</FieldName>
<Value>John</Value>
</UserProperty>
<UserProperty CreatedDate="2013-12-03T11:36:31.423">
<FieldName>User MI</FieldName>
<Value>Q</Value>
</UserProperty>
<UserProperty CreatedDate="2013-11-19T09:56:44.66">
<FieldName>User Last Name</FieldName>
<Value>Public</Value>
</UserProperty>
<UserProperty CreatedDate="2013-11-14T16:41:12.803">
<FieldName>User SSN</FieldName>
<Value>111-22-3333</Value>
</UserProperty>
</UserProperties>
</User>
</UserInformation>
Here are my objects:
public class EntityProperty
{
[XmlIgnore]
public int FieldId { get; set; }
public string FieldName { get; set; }
[XmlIgnore]
public int FieldSortOrder { get; set; }
[XmlAttribute()]
public DateTime CreatedDate { get; set; }
[XmlIgnore]
public bool IsIterative { get; set; }
public string Value { get; set; }
public EntityTreeBase Entity { get; set; }
public EntityProperty() { }
public EntityProperty(int fieldId, string fieldName, int fieldSortOrder, DateTime createdDate, bool isIterative, string valueIn)
{
FieldId = fieldId;
FieldName = FieldName;
FieldSortOrder = fieldSortOrder;
CreatedDate = createdDate;
IsIterative = isIterative;
Value = valueIn;
}
}
public class EntityTreeBase
{
[XmlIgnore]
public long EntityId { get; set; }
[XmlIgnore]
public long? ParentEntityId { get; set; }
[XmlIgnore]
public int EntityDefinitionId { get; set; }
[XmlIgnore]
public int DestinationId { get; set; }
[XmlIgnore]
public int Level { get; set; }
[XmlAttribute("EntityInfo")]
public string EntityDefinitionName { get; set; }
public EntityTreeBaseCollection Children { get; set; }
public EntityPropertiesCollection Properties { get; set; }
public EntityTreeBase() { }
public EntityTreeBase(long entityId, long? parentEntityId, int entityDefinitionId, int destinationId, int level, string entityDefinitionName)
{
EntityId = entityId;
ParentEntityId = parentEntityId;
EntityDefinitionId = entityDefinitionId;
DestinationId = destinationId;
Level = level;
EntityDefinitionName = entityDefinitionName;
}
public bool HasChildren
{
get { return (Children != null && Children.Count > 0); }
}
public bool HasProperties
{
get { return (Properties != null && Properties.Count > 0); }
}
public static EntityTreeBase BuildTree(EntityTreeBaseCollection collection, EntityTreeBase parent)
{
parent.Properties = EntityPropertiesCollection.GetProperties(parent.DestinationId, parent.EntityId, parent.EntityDefinitionId);
parent.Children = new EntityTreeBaseCollection();
foreach (EntityTreeBase item in EntityTreeBaseCollection.FindChildEntities(collection, parent.EntityId))
{
parent.Children.Add(BuildTree(EntityTreeBaseCollection.GetChildren(item.EntityId, item.Level, item.DestinationId), item));
}
if (!parent.HasChildren)
{
parent.Children = null;
}
if (!parent.HasProperties)
{
parent.Properties = null;
}
return parent;
}
}
So, as is hopefully obvious, there are no object types named "Medication" or "User", these must be inferred from the data. So I need to know how to use values from the data to change my element names, but I need to figure out how to crawl the object tree so each element name is changed based on the associated EntityDefinitionName. I'm using recursion to populate my object tree prior to serialization. I know the following code works to rename my XmlRoot:
XmlAttributeOverrides xmlOverrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
XmlRootAttribute rootAttr = new XmlRootAttribute();
rootAttr.ElementName = collection.Find(e => e.Level == 1).EntityDefinitionName.Replace(" ", "");
attribs.XmlRoot = rootAttr;
But I need to figure out how to change each element name based on the EntityDefinitionName associated with that element or node.
Thanks in advance!
Although I think you can achieve that by using custom serialization I want to present a different approach to solving your question by using an XSLT stylesheet.
This stylesheet transforms your input xml to your desired output xml:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="ArrayOfEntityTreeBase">
<UserInformation >
<xsl:apply-templates />
</UserInformation>
</xsl:template>
<xsl:template match="EntityTreeBase[#EntityInfo='User']">
<User>
<xsl:apply-templates />
</User>
</xsl:template>
<xsl:template match="Children">
<UserMedications>
<xsl:apply-templates />
</UserMedications>
</xsl:template>
<xsl:template match="EntityTreeBase[#EntityInfo='User Medication']">
<UserMedication>
<xsl:apply-templates />
</UserMedication>
</xsl:template>
<xsl:template match="EntityTreeBase[#EntityInfo='User Medication']/Properties">
<MedicationProperties>
<xsl:apply-templates />
</MedicationProperties>
</xsl:template>
<xsl:template match="EntityTreeBase[#EntityInfo='User']/Properties">
<UserProperties>
<xsl:apply-templates/>
</UserProperties>
</xsl:template>
<xsl:template match="EntityTreeBase[#EntityInfo='User']/Properties/EntityProperty">
<xsl:element name="UserProperty">
<xsl:copy-of select="#*"/>
<xsl:copy-of select="*" />
</xsl:element>
</xsl:template>
<xsl:template match="EntityTreeBase[#EntityInfo='User Medication']/Properties/EntityProperty">
<xsl:element name="MedicationProperty">
<xsl:copy-of select="#*"/>
<xsl:copy-of select="*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
This is the code that you can use the run the transformation in your c# code:
var xml = File.Open("input.xml", FileMode.Open); // or any stream
var xslTrans = new XslCompiledTransform();
xslTrans.Load(XmlReader.Create(File.Open("yourxslfile.xlst", FileMode.Open)));
var output = File.Create("output.xml"); // or a stream
var xw = XmlWriter.Create(output);
xslTrans.Transform(XmlReader.Create(xml), xw );
xw.Close();
I want to desirialize an XML file to C# Objects. My objects are as follows
[Serializable]
[XmlRoot(ElementName = "Collection")]
public class Collection
{
public Collection()
{
Artiesten = new List<Artiest>();
Albums = new List<Album>();
Nummers = new List<Nummer>();
}
[XmlElement("Artiesten")]
public List<Artiest> Artiesten { get; set; }
[XmlElement("Albums")]
public List<Album> Albums { get; set; }
[XmlElement("Nummers")]
public List<Nummer> Nummers { get; set; }
}
[Serializable]
public class Artiest
{
[XmlAttribute("artiestid")]
public int ArtiestId { get; set; }
[XmlElement(ElementName = "Naam")]
public String Naam { get; set; }
[XmlElement(ElementName = "Albums")]
public List<Album> Albums { get; set; }
}
[Serializable]
public class Nummer
{
[XmlAttribute("nummerid")]
public int NummerId { get; set; }
[XmlElement(ElementName = "titel")]
public String Titel { get; set; }
[XmlElement(ElementName = "duur")]
public String Duration { get; set; }
}
My XML is this:
<Collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Artiesten>
<Artiest artiestid="1">
<Naam>Harry</Naam>
<Albums>
<Album albumid="1">
<Titel>Album1</Titel>
<prijs valuta="Euro">19.99</prijs>
<uitgiftejaar>1999</uitgiftejaar>
<Nummers>
<Nummer nummerid="1">
<titel>happy Sundays</titel>
<duur>PT02M02S</duur>
</Nummer>
</Nummers>
</Album>
</Albums>
</Artiest>
</Artiesten>
<Albums>
<Album albumid="1">
<Titel>Album1</Titel>
<prijs valuta="Euro">19.99</prijs>
<uitgiftejaar>1999</uitgiftejaar>
<Nummers>
<Nummer nummerid="1">
<titel>Happy Sundays</titel>
<duur>PT02M02S</duur>
</Nummer>
</Nummers>
</Album>
</Albums>
<Nummers>
<Nummer nummerid="1">
<titel>Happy Sundays</titel>
<duur>PT02M02S</duur>
</Nummer>
</Nummers>
</Collection>
And I'm trying to desirialize like this:
XDocument doc = XDocument.Load(file);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Collection));
using (var reader = doc.Root.CreateReader())
{
Collection collection = (Collection) xmlSerializer.Deserialize(reader);
}
For some reason I can't find the lists in the Collection object are all empty. Debugging shows that the loaded file in XDocument is valid.
EDIT: I managed to narrow down the problem. It does deserialize the lists correctly, only all property's of the Objects in those lists are empty.
Found my answer
I had to edit My list Attributes to this:
[XmlElement("Artiesten", typeof(List<Artiest>))]
public List<Artiest> Artiesten { get; set; }
[XmlElement("Albums", typeof(List<Album>))]
public List<Album> Albums { get; set; }
[XmlElement("Nummers", typeof(List<Nummer>))]
public List<Nummer> Nummers { get; set; }
Collection collection = null;
string path = "file.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Collection));
StreamReader reader = new StreamReader(path);
collection = (Collection)serializer.Deserialize(reader);
reader.Close();
You need to re move the [XmlElement] tags from your lists. Otherwise it works with a different XML structure.
For example, rather than nest all your Artiest objects within a single Artiesten element (which is what your current XML is), it will actually set them adjacent to each other like this:
<Artiesten artiestid="1">
<Naam>Harry</Naam>
<Albums>
<Album albumid="1">
<Titel>Album1</Titel>
<prijs valuta="Euro">19.99</prijs>
<uitgiftejaar>1999</uitgiftejaar>
<Nummers>
<Nummer nummerid="1">
<titel>happy Sundays</titel>
<duur>PT02M02S</duur>
</Nummer>
</Nummers>
</Album>
</Albums>
</Artiesten>
<Artiesten artiestid="2">
<Naam>Harry</Naam>
<Albums>
<Album albumid="1">
<Titel>Album1</Titel>
<prijs valuta="Euro">19.99</prijs>
<uitgiftejaar>1999</uitgiftejaar>
<Nummers>
<Nummer nummerid="1">
<titel>happy Sundays</titel>
<duur>PT02M02S</duur>
</Nummer>
</Nummers>
</Album>
</Albums>
</Artiesten>
<Artiesten artiestid="3">
<Naam>Harry</Naam>
<Albums>
<Album albumid="1">
<Titel>Album1</Titel>
<prijs valuta="Euro">19.99</prijs>
<uitgiftejaar>1999</uitgiftejaar>
<Nummers>
<Nummer nummerid="1">
<titel>happy Sundays</titel>
<duur>PT02M02S</duur>
</Nummer>
</Nummers>
</Album>
</Albums>
</Artiesten>
So try redefining your classes as such:
[Serializable]
[XmlRoot(ElementName = "Collection")]
public class Collection
{
public Collection()
{
Artiesten = new List<Artiest>();
Albums = new List<Album>();
Nummers = new List<Nummer>();
}
public List<Artiest> Artiesten { get; set; }
public List<Album> Albums { get; set; }
public List<Nummer> Nummers { get; set; }
}
[Serializable]
public class Artiest
{
[XmlAttribute("artiestid")]
public int ArtiestId { get; set; }
[XmlElement(ElementName = "Naam")]
public String Naam { get; set; }
public List<Album> Albums { get; set; }
}
You want XmlArray, not XmlElement:
[XmlArray("Artiesten")]
[XmlArrayItem("Artiest")]
public List<Artiest> ...
Actually this is the default behaviour for lists, so you also just remove the attribute completely.
Here's how I started:
System.Xml.Serialization.XmlRootAttribute xRoot = new System.Xml.Serialization.XmlRootAttribute();
xRoot.IsNullable = true;
xRoot.Namespace = "urn:schemas-microsoft-com:rowset";
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(ProductSalesList), xRoot);
System.Xml.XmlReader reader = new System.Xml.XmlTextReader(path + "\\" + file);
eltOnly e = (eltOnly)serializer.Deserialize(reader);
But I don't know how to continue. Here's the xml file:
<xml xmlns:s='uuid:00000000-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-0000-11d1-A29F-00AA00C14882'
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
<s:ElementType name='row' content='eltOnly'>
<s:AttributeType name='Art' rs:number='1' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='Name' rs:number='2' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='Sum' rs:number='3' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='float' dt:maxLength='8' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Cost' rs:number='4' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='float' dt:maxLength='8' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:extends type='rs:rowbase'/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row Art='0000000001' Name='Brand pils 0,2' Sum='153' Cost='304'/>
<z:row Art='0000000002' Name='Brand pils 0,25' Sum='11' Cost='25.300000000000004'/>
<z:row Art='0000000003' Name='Brand pils 0,5' Sum='3' Cost='13.799999999999999'/>
</rs:data>
</xml>
How to continue? How should I call the class which would have the Deserialization attribute?
Here's what I did:
[Serializable()]
public class Elt
{
[System.Xml.Serialization.XmlElement]
public string Art { get; set; }
[System.Xml.Serialization.XmlElement]
public string Name { get; set; }
[System.Xml.Serialization.XmlElement]
public float? Sum { get; set; }
[System.Xml.Serialization.XmlElement]
public float? Cost { get; set; }
}
[Serializable, System.Xml.Serialization.XmlRoot("eltOnly")]
public class eltOnly
{
[System.Xml.Serialization.XmlElement]
public List<Elt> Elt { get; set; }
}
And I get error: There is an error in XML document (1, 2). " was not expected."
This linq2xml should do what you want...
XDocument doc=XDocument.Load(yourXml);
XNamespace rs="urn:schemas-microsoft-com:rowset";
XNamespace z="#RowsetSchema";
var lstRows=doc.Descendants(rs+"data").Elements(z+"row").Select(x=>
new
{
art=x.Attribute("Art").Value,
name=x.Attribute("Name").Value,
sum=(float?)x.Attribute("Sum"),
cost=(float?)x.Attribute("Cost")
}
);
You can now iterate over lstRows
foreach(var row in lstRows)
{
row.art;//string
row.name;//string
row.sum;//float?
row.cost;//float?
}