Reputation: 61
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 )
}
}
}
}
};
Upvotes: 1
Views: 692
Reputation: 34421
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; }
}
}
Upvotes: 1
Reputation: 189
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?
Upvotes: 2
Reputation: 189
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.
Upvotes: 1