How to read data from xml file using linq to xml? - c#

Trying to read this xml using Linq to XML
<Root>
<shelves>
<bookNumber>12</bookNumber>
<coverType unit="H">soft</coverType>
<pages>100</pages>
<Weight units="lb">1.2</Weight>
<chapter sample="1">example 1</<chapter>
<chapter sample="2">example 2</<chapter>
<chapter sample="3">example 3</<chapter>
<chapter sample="4">example 4</<chapter>
<chapter sample="5">example 5</<chapter>
<chapter sample="6">example 6</<chapter>
<chapter sample="7">example 7</<chapter>
<chapter .................</chapter>
<chapter .................</chapter>
<chapter .................</chapter>
<chapter .................</chapter>
<chapter .................</chapter>
..............
</shelves>
</Root>
Thats the code i am trying with:-. But How will read values all the elements 'Chapter'?
var book = from b in xml.Root.Elements("shelves")
select b;
foreach (var s in book)
{
booknumber = s.Element("bookNumber").Value,
covertype = s.Element("bookNumber").Value,
coverTypeUnit = s.Element("bookNumber").Attribute("unit").Value,
...........
chapter = s.Element("bookNumber").Value ????
}

You may find these links usefull:
linq-to-read-xml
101 LINQ Samples

var values = s.Elements("chapter").Select(n => n.Value).ToArray();
Furthermore, you're reading from the same element (booknumber) over and over. You might want to check your code.
EDIT: to also yield the attribute:
s.Elements("chapter").
Select(n => new {Topic = n.Attribute("topic").Value, Value = n.Value}).
ToArray();

Related

LINQ to XML basic codes

developers !!
I'm studying LINQ to XML with "C# in a Nutshell".
I'd like to grab two lines from the XML file.
When I find myself in times of trouble
Mother Mary comes to me
The file is like this;
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0">
<file datatype="x-sdlfilterframework2">
<header>
<reference></reference>
</header>
<body>
<trans-unit translate="no" id="20873339caf8">
<source><x id="0"/></source>
</trans-unit>
<group>
<sdl:cxts><sdl:cxt id="1"/></sdl:cxts>
<trans-unit id="fb3052898e68">
<source>When I find myself in times of trouble</source>
</trans-unit>
</group>
<group>
<sdl:cxts><sdl:cxt id="1"/></sdl:cxts>
<trans-unit id="f3e2e9ca583c">
<source>Mother Mary comes to me</source>
</trans-unit>
</group>
</body>
</file>
</xliff>
Actually, I have tried ALL kinds of code I could do with the book.
But, I have failed and am in the desperate state.
Please help.
(There come some more lines. As song goes. The pattern is very strict. It comes with group, group and group elements.)
Regards
(EDIT)
My first try is like this.
I have to practice with the name of elements.
so..
XElement ALL = XElement.Load( myPATH );
string RSLT = "";
int CNT = 0;
foreach( XElement x in ALL.Elements() )
{
CNT ++;
RSLT += CNT + ". " + x.Name + "\n";
}
MessageBox.Show( RSLT );
It gives me just "1. file".
I was expecting "file header body trans-unit group..".
I think this should do the trick:
var doc = XDocument.Load(path);
foreach(var srcElem in doc.Descendants("source").Skip(1))
{
Console.WriteLine((string)srcElem);
}
Try this:
var doc = XDocument.Load("filename.xml");
string[] lines = doc.Descendants("body")
.Elements("group")
.Elements("trans-unit")
.Elements("source")
.Select(e => (string)e).ToArray();

Parsing XML file with LINQ getting wrong information

Im trying to parse an XML file from my program and I'm basing my code off this answer.
However the XML I'm using now is a bit more complex where I need to fill several nested lists with classes. Here are my two classes
public class Picture
{
private int mPicNumber;
private int mPicDuration;
private List<string> mToSay = new List<string>();
public Picture(int picNumber, int picDuration, List<string> toSay){...}
}
public class Sequence
{
string mName;
int mNumber;
List<Picture> mPictures = new List<Picture>();
public Sequence(string name, int number, List<Picture> pictures){...}
}
The XML looks like this
<sequences>
<sequence>
<name>Seq 2</name>
<number>1</number>
<picture>
<number>1</number>
<duration>5</duration>
<rows>
<text>text1</text>
<text>text2</text>
<text>text3</text>
</rows>
</picture>
<picture>
<number>2</number>
<duration>5</duration>
<rows>
<text>text1</text>
<text>text2</text>
<text>text3</text>
</rows>
</picture>
<picture>
<number>3</number>
<duration>5</duration>
<rows>
<text>text1</text>
<text>text2</text>
<text>text3</text>
</rows>
</picture>
</sequence>
<sequence>
<name>Seq 2</name>
<number>1</number>
<picture>
<number>1</number>
<duration>5</duration>
<rows>
<text>text1</text>
<text>text2</text>
<text>text3</text>
</rows>
</picture>
<picture>
<number>2</number>
<duration>5</duration>
<rows>
<text>text1</text>
<text>text2</text>
<text>text3</text>
</rows>
</picture>
<picture>
<number>3</number>
<duration>5</duration>
<rows>
<text>text1</text>
<text>text2</text>
<text>text3</text>
</rows>
</picture>
</sequence>
</sequences>
Here is the code for parsing the XML
XDocument xmlDoc = XDocument.Load("Sequences.xml");
List<Picture> pictures;
List<string> toSay;
mSequences = xmlDoc.Descendants("sequence").
Select(be => new Sequence(
(string)be.Element("name"),
(int)be.Element("number"),
pictures = xmlDoc.Descendants("picture").
Select(bf => new Picture(
(int)bf.Element("number"),
(int)bf.Element("duration"),
toSay = xmlDoc.Descendants("rows").
Select(bg =>
(String)bg.Element("text")).ToList())).ToList())).ToList();
After I run this I get a list with 2 Sequences (which is correct) and the name and number is correct. However Each sequence contain all 6 pictures from the XML file and those pictures doesn't contain anything from within the rows tag. I tried changing Descendants to Elements on the two inner lists but then I got 0 pictures in all sequences instead. I will admit I'm not very good at LINQ and this is very confusing to me.
The problem with your code is here pictures = xmlDoc.Descendants("picture"). & toSay = xmlDoc.Descendants("rows").. You are again querying the XML from the top rather you should be querying the already filtered data. You should use the instance variable be & bf respectively.
This will give you the expected output:-
var res = xdoc.Root.Elements("sequence")
.Select(be => new Sequence(
(string)be.Element("name"),
(int)be.Element("number"),
pictures = be.Elements("picture")
.Select(bf => new Picture(
(int)bf.Element("number"),
(int)bf.Element("duration"),
toSay = bf.Element("rows").Elements("text")
Select(bg =>
(String)bg).ToList()))
.ToList()))
.ToList();
Also, note how I have replaced Descendants with Elements. If you XML contains some inner node with same tag then you will get unexpected output.
pictures = xmlDoc.Descendants("picture")
It looks like you get the Pics from the whole document xmlDoc.Decendants,
but instead you need to get it for each be object I think. I can`t check it right now but i guess be.Decentans should be okay?

XmlDocument in an array like object

I googled for hours and didn't find anything.
I'm trying to make a Metro App which is reading from an online XML Service. Getting the XML is not the problem, i'm simply doing it like this ->
var xmlDoc = await XmlDocument.LoadFromUriAsync(new Uri(url));
but now the problem is, how to convert it into a list or something readable like this.
The XML I want to read is really huge and i don't want to go through all nodes with foreach.
A simple Array/List with all nodes and innerText as Value would be awesome.
Is this possible? If yes.. how ?
The structure of my XML is like this ->
<?xml version="1.0" encoding="UTF-8"?>
<city>
...
<credit>
...
</credit>
<forecast>
<date value="2013-11-08">
...
<time value="06:00">
...
</time>
<time value="11:00">
...
</time>
<time value="17:00">
...
</time>
<time value="23:00">
...
</time>
...
</date>
<date value="2013-11-09">
<same content here>
</date>
<date value="2013-11-09">
<same content here>
</date>
</forecast>
</city>
as you can see... there's a lot of information in the XML and I need nearly everything. In Actionscript I would realize it with a XMLList and make 3 Lists of the date Tags with content, so i can use
xmllist1.time[0] - xmllist1.time[3]
xmllist2.time[0] - xmllist2.time[3]
xmllist3.time[0] - xmllist3.time[3]
to get my data.
And now i want this XMLList in C#... I hope it's possible...Thx 4 help
If I understand you correctly, you want to parse the list of "city" items from the xml.
I do something similar using XDocument and Linq like this and it should work for you:
XDocument xdoc = <add your code to get xml from url>;
var ns = xdoc.Root.GetDefaultNamespace();
var cityList = from query in xdoc.Descendants(ns + "city")
select new CityItem
{
Date = (string)query.Element(ns + "date").Attribute("value").Value,
Time = (string)query.Element(ns + "time").Attribute("value").Value
};
public class CityItem
{
public string Date {get;set;}
public string Time {get;set;}
}

Collect attributes from a XML file by XMLReader

I have an XML file as below.
<BOOK bnumber="1" bname="Book">
<CHAPTER cnumber="1">
<Sentence vnumber="1">This is the sentence 1.</Sentence>
<Sentence vnumber="2">This is the sentence 2.</Sentence>
<Sentence vnumber="3">This is the sentence 3.</Sentence>
</CHAPTER>
<CHAPTER cnumber="2">
<Sentence vnumber="1">Hello World 1.</Sentence>
<Sentence vnumber="2">Hello World 2.</Sentence>
<Sentence vnumber="3">Hello World 3.</Sentence>
<Sentence vnumber="4">Hello World 4.</Sentence>
</CHAPTER>
<CHAPTER cnumber="3">
<Sentence vnumber="1">Good morning 1.</Sentence>
<Sentence vnumber="2">Good morning 2.</Sentence>
<Sentence vnumber="3">Good morning 3.</Sentence>
</CHAPTER>
</BOOK>
What I want is to collect the attributes of "CHAPTER".
The goal is to get
Chapter={"Chapter 1";"Chapter 2","Chapter 3"};
Current I use tradition method,
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"C:\books.xml"); //load the xml file into our document
XmlNodeList nodes = xdoc.SelectNodes(#"//BOOK/CHAPTER[#cnumber='" + chap
string sentences = "";
foreach(XmlNode node in nodes) {
sentences += node.InnerText + "; ";
}
but I want to use XMLReader because the XML file is big, I don't want to load it in memory.
Thanks for help.
Well basicly you can do like this:
var chapters = new List<string>();
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
reader.ReadToFollowing("CHAPTER");
reader.MoveToFirstAttribute();
string chapterNumber = reader.Value;
chapters.Add("Chapter " + chapterNumber);
}
where the xmlString is your xml.
This will find the first chapter and get the attribute from it and add it to a list of chapters.

XML Parsing in C# .net 4

I have following xml How can I read xml to get list of Sura nodes like this
var Suras = XMLNodes **//how to use xpath to load xmlnodes of sura**
foreach (var sura in suras)
{
var ayas = sura. **//how to use xpath to load xmlnodes of aya for this sura node**
}
XML
<?xml version="1.0" encoding="utf-8" ?>
<quran>
<sura index="1" name="الفاتحة">
<aya index="1" text="In the name of Allah, the Entirely Merciful, the Especially Merciful."/>
<aya index="2" text="[All] praise is [due] to Allah, Lord of the worlds -"/>
</sura>
<sura index="114" name="الناس">
<aya index="1" text="Say, "I seek refuge in the Lord of mankind,"/>
<aya index="2" text="The Sovereign of mankind."/>
<aya index="3" text="The God of mankind,"/>
<aya index="4" text="From the evil of the retreating whisperer -"/>
<aya index="5" text="Who whispers [evil] into the breasts of mankind -"/>
<aya index="6" text="From among the jinn and mankind.""/>
</sura>
</quran>
Do you particularly want to use XPath? I'd just use LINQ to XML:
XDocument doc = XDocument.Load("file.xml");
var suras = doc.Root.Elements("sura");
foreach (var sura in suras)
{
var ayas = suras.Elements("aya");
...
}

Categories

Resources