Search through the elements of an xml document in windows phone 8 - c#

I have an xml document i am trying to query and link the data to a listbox in windows phone 8 but i have so far failed. the examples online dont seem to bring what exactly i want.
Below is what i have at the moment. in xml.
This is my xml document(mydata.cml)
<resources>
<songCover>
<item>Images/song1</item>
<item>Images/song2</item>
.....
</songCover>
<songName>
<item>song1</item>
<item>song2</item>
.....
</songName>
<releaseYear>
<item>2015</item>
<item>2014</item>
.....
</releaseYear>
and the c#
XDocument doc=XDocument.Load("mydata.xml");
var data1=from Q in doc.Descedants("songCover") select new{Item=Q.Element("item").Value;
var data2=from Q in doc.Descedants("songName") select new{Item=Q.Element("item").Value;
var data3=from Q in doc.Descedants("releaseYear") select new{Item=Q.Element("item").Value;
foreach(var x in data1)
foreach(var y in data2)
foreach(var z in data3)
//create a list of songs with there data eg [songCover1,song1,2015],[songCover2,song2,2014] etc
this is my xaml
<longlistselector>
......
<stackPanel>
<image height=”100” width=”100” source={Binding data1} horizontal-alignment=left/>
<textblock horizontal-alignment=right text={Binding data 2}/>
<texblock horizontal-alignment=right text={Binding data 3}/>
</stackPanel>
......
</longlistselector>
Thank You in advance.

Assuming that number of items in each collection (songCovers, songNames, and releaseYears) are the same, and they corresponds by index, you can do this way :
XDocument doc = XDocument.Load("mydata.xml");
var data1 = doc.Descedants("songCover")
.Elements("item")
.Select(o => o.Value)
.ToList();
var data2 = doc.Descedants("songName")
.Elements("item")
.Select(o => o.Value)
.ToList();
var data3 = doc.Descedants("releaseYear")
.Elements("item")
.Select(o => o.Value)
.ToList();
for(int i=0; i<data1.Count; i++)
{
var songCover = data1[i];
var songName = data2[i];
var releaseYear = data3[i];
//combine the 3 values above as needed
}

Is this what you are looking for?. I am assuming(base on what you wrote in your snippet as comment) covers, names and years are respectively at same position.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("path_here");
XmlNodeList covers = xmlDoc.SelectNodes("/songCover/item");
XmlNodeList names = xmlDoc.SelectNodes("/songName/item");
XmlNodeList years = xmlDoc.SelectNodes("/releaseYear/item");
for(int i=0;i<covers.Count; i++)
{
Console.WriteLine("[ "+ covers[i].Value +", " + names[i].Value + ", "+ years[i].Value + " ]");
}

XDocument xdoc = XDocument.Load("file_path_here");
List<xElement> covers = xDoc.XPathSelectElements("/songCover/item").ToList();
List<xElement> names = xDoc.XPathSelectElements("/songName/item").ToList();
List<xElement> years = xDoc.XPathSelectElements("/releaseYear/item").ToList();
for (int i = 0; i < covers.Count; i++)
{
Console.WriteLine("[ " + covers[i].Value + ", " + names[i].Value + ", " + years[i].Value + " ]");
}

Related

Reading XML data using XmlDocument with C# - Reading attribute data and splitting the results

I'm trying to read some XML data using XmlDocument and having a few challenges.
My issues are as follows:
When I try to get the bfihost value, it gives me the bfihost, propwet and saar element values combined as a single output. Why is this and how do I get just the bfihost?
Each Depth element has an attribute named duration. My first foreach loop writes the string durationString to the console, but it doesn't seem to find any attributes called duration in the XmlNode chldNode.
This issue is probably less important, but when I find the value for the element ReturnPeriods for example I can only retrieve all the values separated by commas. This isn't an issue as I've just used the Split(',') method and assigned it to an array and looped through that. I was curious if XmlDocument had a more elegant way of doing this?
Thanks for any help received.
Here is a stripped down version of the XML data. The , ... have been added as there is a lot more data in the actual xml file.
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<FEHCDROMExportedDescriptors appVersion="2.0.0.0" version="2.0.1">
<PointDescriptors y="111111" x="222222" grid="GB">
<bfihost>0.386</bfihost>
<propwet>0.3</propwet>
<saar>643</saar>
</PointDescriptors>
<PointDDF2013Values>
<ReturnPeriods>
<![CDATA[
1.3, 1.58, 2, ...
]]>
</ReturnPeriods>
<Depths duration="0.083">
<![CDATA[
3.27693489525396, 3.98688804941076, 4.68688804941076, ...
]]>
</Depths>
<Depths duration="0.25">
<![CDATA[
5.37693489525396, 6.51484587430874, 7.81484587430874, ...
]]>
</Depths>
<Depths duration="0.5">
<![CDATA[
6.87693489525396, 8.38688804941076, 10.0017339237195, ...
]]>
</Depths>
</PointDDF2013Values>
</FEHCDROMExportedDescriptors>
The code I have written is as follows:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(file);
XmlTextReader reader = new XmlTextReader(file);
XmlNode node = xmlDoc.ReadNode(reader);
string durationString;
foreach (XmlNode chldNode in node.ChildNodes)
{
//Read the attribute duration
if (chldNode.Name == "Depths")
{
if (chldNode.HasChildNodes)
{
foreach (XmlNode item in node.ChildNodes)
{
durationString = chldNode.Attributes["duration"].Value;
Console.WriteLine("durations[]: " + durationString);
}
}
}
}
XmlNodeList pointDescriptors = xmlDoc.GetElementsByTagName("PointDescriptors");
XmlElement xmlElement = (XmlElement)pointDescriptors[0];
// Get coordinates
XmlAttribute y = xmlElement.GetAttributeNode("y");
Console.WriteLine("y[]: " + y.InnerXml);
XmlAttribute x = xmlElement.GetAttributeNode("x");
Console.WriteLine("x[]: " + y.InnerXml);
// for some reason returns the bfi Host, propwet and saar
XmlNodeList bfihost = xmlDoc.GetElementsByTagName("bfihost");
Console.WriteLine("bfihost[]: " + pointDescriptors[0].InnerText);
// returns all return periods as a string.
XmlNodeList returnPeriods = xmlDoc.GetElementsByTagName("ReturnPeriods");
//Console.WriteLine("Return Periods[]: " + returnPeriods[0].InnerText);
//I can split the string by commas and remove white spaces as follows
string[] returnPeriodsArray = returnPeriods[0].InnerText.Split(',').Select(sValue => sValue.Trim()).ToArray();
foreach (string s in returnPeriodsArray)
{
//System.Console.Write("{0} ", s);
}
int k = 0;
//Loop through all the depths, and split the results
XmlNodeList depths = xmlDoc.GetElementsByTagName("Depths");
XmlAttribute duration;
for (int i = 0; i < depths.Count; i++)
{
if (depths[i].InnerText.Length > 0)
{
System.Console.Write("{0} ", "\n\n" + "Depth xxx" + "\n\n");
string[] depthsArray = depths[i].InnerText.Split(',').Select(sValue => sValue.Trim()).ToArray();
foreach (string s in depthsArray)
{
System.Console.Write("{0} ", "(" + returnPeriodsArray[k] + ") - " + s + "\n");
k++;
if (k > 21)
{
k = 0;
}
}
}
}
And the output I get is:
y[]: 11111 //correct
x[]: 22222 //correct
bfihost[]: 0.3860.3643 //this is combination of three elements for some reason?
///Here I try to get the depth data but nothing is returned.
Depth xxx // xxx is just a place holder until I can fix the above issue.
(1.3) - 3.27693489525396 //all these outputs are correct.
(1.58) - 3.98688804941076
(2) - 4.68688804941076
Depth xxx
(1.3) - 5.37693489525396
(1.58) - 6.51484587430874
(2) - 7.81484587430874
Depth xxx
(1.3) - 6.87693489525396
(1.58) - 8.38688804941076
(2) - 10.0017339237195
It is better to use LINQ to XML API. It is available in the .Net Framework since 2007.
c#
void Main()
{
const string fileName = #"e:\Temp\FEHCDROME.xml";
XDocument xdoc = XDocument.Load(fileName);
XElement xelem = xdoc.Descendants("PointDescriptors").FirstOrDefault();
Console.WriteLine("PointDescriptors:");
Console.WriteLine("y[]: {0}", xelem.Attribute("y").Value);
Console.WriteLine("x[]: {0}", xelem.Attribute("x").Value);
Console.WriteLine("bfihost[]: {0}", xelem.Element("bfihost").Value);
XElement rp = xdoc.Descendants("ReturnPeriods").FirstOrDefault();
Console.WriteLine("{0}ReturnPeriods:", Environment.NewLine);
foreach (string s in rp.Value.Split(',').Select(sValue => sValue.Trim()).ToArray())
{
Console.WriteLine("{0} ", s);
}
Console.WriteLine("{0}Depths:", Environment.NewLine);
foreach (XElement dp in xdoc.Descendants("Depths"))
{
foreach (string s in dp.Value.Split(',').Select(sValue => sValue.Trim()).ToArray())
{
Console.WriteLine("{0} ", s);
}
}
}
Output
PointDescriptors:
y[]: 111111
x[]: 222222
bfihost[]: 0.386
ReturnPeriods:
1.3
1.58
2
...
Depths:
3.27693489525396
3.98688804941076
4.68688804941076
...
5.37693489525396
6.51484587430874
7.81484587430874
...
6.87693489525396
8.38688804941076
10.0017339237195
...

Html Agility Pack xpath IEnumerable

I can not add html code, because it is very very big! 5 scrolls or more. Please, follow link in htmlWeb.load().
I look at this code already 2 hours and I can not figure out what is wrong.
HtmlWeb htmlWeb = new HtmlWeb {OverrideEncoding = Encoding.Default};
HtmlAgilityPack.HtmlDocument document = htmlWeb.Load("https://www.parimatch.com/en/sport/futbol/germanija-bundesliga");
var matches = document.DocumentNode.SelectNodes("//tr[#class='bk']").
Select(tr => new FootballMatch()
{
Number = string.Join(" ", tr.SelectNodes("./td[1]//text()[normalize-space()]").Select(t =>t.InnerText)),
Time = string.Join(" ", tr.SelectNodes("./td[2]//text()[normalize-space()]").Select(t => t.InnerText)),
Teams = string.Join(" ", tr.SelectNodes("./td[3]//text()[normalize-space()]").Select(t => t.InnerText)),
Allowance = string.Join(" ", tr.SelectNodes("./td[4]//text()[normalize-space()]").Select(t => t.InnerText)),
CoefficientAllowance = string.Join(" ", tr.SelectNodes("./td[5]//text()[normalize-space()]").Select(t => t.InnerText)),
Total = tr.SelectSingleNode("./td[7]//text()[normalize-space()]").InnerText,
P1 = tr.SelectSingleNode("./td[10]//text()[normalize-space()]").InnerText,
X = tr.SelectSingleNode("./td[11]//text()[normalize-space()]").InnerText,
/*P2 = tr.SelectSingleNode("./td[12]//text()[normalize-space()]").InnerText,
P1X = tr.SelectSingleNode("./td[13]//text()[normalize-space()]").InnerText,
P1P2 = tr.SelectSingleNode("./td[14]//text()[normalize-space()]").InnerText,
P2X = tr.SelectSingleNode("./td[15]//text()[normalize-space()]").InnerText*/
});
P2,P1X,P1P2,P2X always null.
and it is possible to do this code more neater?
When you click on an event , a popup menu appears , this data is read too , but I do not need this . How can I disable this ?
This is also not the prettiest. But it works. Still some work needs to be done in respect to sperating certain cells. Since some <td>s contain <br> to separate lines. Hope this helps you moving on.
string xpath = "//tr[#class='bk']";
HtmlNodeCollection matches = htmlDoc.DocumentNode.SelectNodes(xpath);
List<List<string>> footballMatches = new List<List<string>>();
foreach (HtmlNode x in matches)
{
List<string> mess = new List<string>();
HtmlNodeCollection hTC = x.SelectNodes("./td");
if (hTC.Count > 15)
{
for (int i = 0; i < 15; i++)
{
if (i != 5)
{
mess.Add(hTC[i].InnerText);
}
}
}
footballMatches.Add(mess);
}

Unable to access inner Xml elements

Question Background:
I have extracted the following inner XML from a larger document:
<Counters total="1" executed="1" passed="1" error="0" failed="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" />
Issue:
Using the following code, I have attempted to access each of the elements of the above XML. I need to extract both the name i.e 'total' and its value '1';
XmlDocument innerXmlDoc = new XmlDocument();
innerXmlDoc.LoadXml(node.InnerXml);
XmlElement element = innerXmlDoc.DocumentElement;
XmlNodeList elements = element.ChildNodes;
for (int i = 0; i < elements.Count; i++)
{
//logic
}
If someone can tell me how to get these values that would be great.
You're iterating though the ChildNodes collection of your element and since the element does not have any, you're iterating through the empty nodelist it gives you.
You want to iterate through the Attributes collection instead:
XmlAttributeCollection coll = element.Attributes;
for (int i = 0; i < coll.Count; i++)
{
Console.WriteLine("name = " + coll[i].Name);
Console.WriteLine("value = " + coll[i].Value);
}
It seems you need a Dictionary. Try using LINQ to XML
var values = new Dictionary<string,string>();
var xmlDocument = XDocument.Load(path);
XNamespace ns = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010";
values = xmlDocument
.Descendants(ns + "Counters")
.SelectMany(x => x.Attributes)
.ToDictionary(x => x.Name, x => (string)x));
Managed to solve this myself:
foreach (XmlNode node in nodes)
{
XmlDocument innerXmlDoc = new XmlDocument();
innerXmlDoc.LoadXml(node.InnerXml);
var list = innerXmlDoc.GetElementsByTagName("Counters");
for (int i = 0; i < list.Count; i++)
{
string val = list[i].Attributes["total"].Value;
}
};

c# GetElementsByTagName then read the inner tags values how

this below is example xml
<DOC>
<DOCNO>WSJ870323-0180</DOCNO>
<HL>Italy's Commercial Vehicle Sales</HL>
<DD>03/23/87</DD>
<DATELINE>TURIN, Italy</DATELINE>
<TEXT>Commercial-vehicle sales in Italy rose 11.4% in February from a year earlier, to 8,848 units, according to provisional figures from the Italian Association of Auto Makers.</TEXT>
</DOC>
<DOC>
<DOCNO>WSJ870323-0180</DOCNO>
<HL>Italy's Commercial Vehicle Sales</HL>
<DD>03/23/87</DD>
<DATELINE>TURIN, Italy</DATELINE>
<TEXT>Commercial-vehicle sales in Italy rose 11.4% in February from a year earlier, to 8,848 units, according to provisional figures from the Italian Association of Auto Makers.</TEXT>
</DOC>
and this below code is not working why ?
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.Load("docs.xml");
XmlNodeList elemList = doc.GetElementsByTagName("DOC");
for (int i = 0; i < elemList.Count; i++)
{
string docno = elemList[i].Attributes["DOCNO"].ToString();
}
C# 4.0 wpf
Use this code, assuming you have a valid root:
XmlNodeList elemList = doc.GetElementsByTagName("DOC");
for (int i = 0; i < elemList.Count; i++)
{
var elements = elemList[i].SelectNodes("DOCNO");
if (elements == null || elements.Count == 0) continue;
var firstElement = elements.Item(0);
var docno = firstElement.InnerText;
}
Using Linq To Xml to parse Xml is much more easier. For example,
var xDoc = XDocument.Load("docs.xml");
var docs = xDoc.Descendants("DOC")
.Select(x => new{
DocNo = x.Element("DOCNO").Value,
Text = x.Element("TEXT").Value
})
.ToList();

How to retrieve value from attribute in XML?

What I have:
<?xml version="1.0" encoding="Unicode" standalone="yes"?>
<FiberItems>
<Fiber China="1a" England="1b" Japan="1c" France="1d" Korea="1e"/>
<Fiber China="2a" England="2b" Japan="2c" France="2d" Korea="2e"/>
</FiberItems>
What I want:
1.retrive all the value of "China" into a string array.
2.if a value of China is "1a", retrive all the value of the rest attributes(1b,1c,1d,1e),.
What I do:
1. I write codes for purpose 1 , but never works >_<
XDocument doc = XDocument.Load("/FiberItems.xml");
IEnumerable<string> query = from fiber in doc.Root.Elements("Fiber")
select (string)fiber.Attribute("China");
string[] myString = new string[3];
for (int i = 0; i < 3; i++)
{
foreach (string item in query)
{
myString[i] = (string)item;
}
}
2. for purpose 2, have no idea yet >_<
need helps
You probably shouldn't use an array to collect your data but when you do:
string[] myString = new string[3];
// for (int i = 0; i < 3; i++)
// {
int i = 0;
foreach (string item in query)
{
myString[i] = (string)item;
i += 1;
}
// }
You are doing 3x3 rounds where only 3 are needed.
You can use the following code:
XDocument root = XDocument.Load("/FiberItems.xml");
var attributesChina = root.Elements("FiberItems").Elements("Fiber").Attributes("China");
// attributesChina will contain all the values of china
foreach (XAttribute china in attributesChina)
{
string value = china.value;
}
Check out System.Xml.Linq.
Here's an example to get a list of all the attributes for one element.
var xml = #"<?xml version=""1.0"" encoding=""Unicode"" standalone=""yes""?>
<FiberItems>
<Fiber China=""1a"" England=""1b"" Japan=""1c"" France=""1d"" Korea=""1e""/>
<Fiber China=""2a"" England=""2b"" Japan=""2c"" France=""2d"" Korea=""2e""/>
</FiberItems>";
XDocument doc = XDocument.Parse(xml);
XElement ele = doc.Root.Element("Fiber");
var att = ele.Attributes();
//Load XML element
XElement root = XElement.Parse(File.ReadAllText("/FiberItems.xml"));
//All china attributes (retrieves 1a,2a)
var chinaAttributes= root.Elements().Attributes("China");
//load all rest attributes for china = 1a, loads 1b,1c,1d,1e
var chinaOneARestAttributes = root.Elements().Where(a=>a.Attribute("China")!=null && a.Attribute("China").Value=="1a").Attributes().Select(x=>x.Value).Where(x=>!String.Equals(x,"1a"));
UPDATED for Null Reference Exception. With the data i had tried earlier, i ensured Attribute China was present for all elements.
In XPath:
/FiberItems/Fiber[#China='1a']/#*
gets you all the attributes of Fiber elements with China='1a' and
/FiberItems/Fiber[#China='1a']/#*[local-name()!='China']
gets you the same sequence of attributes excluding the China attribute.
So your requirement is if the attribute China value is "1a" then get all the attribute value of that node. I think it should work
XDocument doc = XDocument.Load("/FiberItems.xml");
IEnumerable<string> query = from fiber in doc.Root.Elements("Fiber")
//condition 1
where (string)fiber.Attribute("China") == "1a"
//condition 2 : Select all except china attribute
select fiber.Attributes().Where(a => a.Name !="China");
Using LINQ to XML:
var xmlStr = #"<?xml version=""1.0"" encoding=""Unicode"" standalone=""yes""?>
<FiberItems>
<Fiber China=""1a"" England=""1b"" Japan=""1c"" France=""1d"" Korea=""1e""/>
<Fiber China=""2a"" England=""2b"" Japan=""2c"" France=""2d"" Korea=""2e""/>
</FiberItems>";
var doc = XDocument.Parse(xmlStr);
var query =
from fiber in doc.Descendants("Fiber")
where (string)fiber.Attribute("China") == "1a"
select String.Join(", ",
(from attr in fiber.Attributes()
where attr.Name != "China"
select (string)attr).ToArray());
This will return a sequence of the other attribute values for each Fiber element that contains a China attribute with the value 1a.

Categories