LINQ to XML basic codes - c#

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();

Related

Trying to calculate xml values from DataGridView

I have successfully created a DataGridView based on the MS walkthrough for reading xml into a DataGridView.
https://msdn.microsoft.com/en-us/library/ekw4dh3f.aspx
I'm now trying to sort the information based on the date of the xml entry to calculate the total ticks present in the xml file. XML sample:
<?xml version="1.0" encoding="utf-8"?>
<Form1>
<Name Key="4/13/2015 6:31:26 AM">
<Date>4/13/2015</Date>
<JobNum>00000</JobNum>
<RevNum>00000</RevNum>
<Task>TimeStar</Task>
<Start>06:31 AM</Start>
<End>06:35 AM</End>
<TotalTime>2163346393</TotalTime>
</Name>
<Name Key="4/13/2015 6:35:11 AM">
<Date>4/13/2015</Date>
<JobNum>27163</JobNum>
<RevNum>00000</RevNum>
<Task>Redlines</Task>
<Start>06:35 AM</Start>
<End>07:35 AM</End>
<TotalTime>36229156954</TotalTime>
</Name>
//etc.
</Form1>
Basically I'm stuck at trying to gather all of the <Date> fields/Rows only and then calculating the <TotalTime> for those rows. I tried doing this from the XML to dynamically create a label based on the unique date fields and then calculate any TotalTime fields that we're in that row.
Get the positions of unique elements in a string[]
I was told that it's easier with the DataGridView, but I believe that is not the case. Can anyone please point me in the right direction on how to sort or filter either this or the previous question. I'm not getting it. I truly don't want the answer written for me. I'm just not able to wrap my head around it.
It seems to me the structure should be something like:
foreach(filter date)
{
uniqueDate = true;
new Label == CreateLabel();
foreach(date = array[x])
{
if (date = array[x])
{
sum = TotalTime[x];
}
}
}
Can anyone help me with the structure of this please. Seems like the code should work for either the DataGridView or reading the XML directly.
Thank you very much in advance for any assistance you can help me with. I REALLY appreciate it :-)
EDIT: This is where I'm getting the XMLException was unhandled - Data at the root level is invalid. Code is modified from Cedric's answer.
public string sum2()
{
var document = XDocument.Parse(filePath);
double getit = 0;
foreach (var dates in document.Root.Elements("Name").GroupBy(i => i.Element("Date").Value))
{
double summ = 0;
foreach (var date in dates)
{
summ += Convert.ToDouble(date.Element("TotalTime").Value);
}
Console.WriteLine("Date {0} = {1}", dates.Key, summ);
getit = summ;
}
double retunthis = getit;
return retunthis.ToString();
}
I'm calling this on the button click with sum2(); Hoping to just see it in action in the console first. Not currently using any of the returned code.
If my understanding is good.
Here is what I have :
var xml = "<Form1><Name Key='4/13/2015 6:31:26 AM'><Date>4/13/2015</Date><JobNum>00000</JobNum><RevNum>00000</RevNum><Task>TimeStar</Task><Start>06:31 AM</Start><End>06:35 AM</End><TotalTime>2163346393</TotalTime></Name><Name Key='4/13/2015 6:35:11 AM'><Date>4/13/2015</Date><JobNum>27163</JobNum><RevNum>00000</RevNum><Task>Redlines</Task><Start>06:35 AM</Start><End>07:35 AM</End><TotalTime>36229156954</TotalTime></Name><Name Key='4/13/2015 6:35:11 AM'><Date>6/13/2015</Date><JobNum>27163</JobNum><RevNum>00000</RevNum><Task>Redlines</Task><Start>06:35 AM</Start><End>07:35 AM</End><TotalTime>36229156954</TotalTime></Name></Form1>";
var document = XDocument.Parse(xml);
foreach (var dates in document.Root.Elements("Name").GroupBy(i => i.Element("Date").Value))
{
double summ = 0;
foreach (var date in dates)
{
summ += Convert.ToDouble(date.Element("TotalTime").Value);
}
Console.WriteLine ("Date {0} = {1}", dates.Key, summ);
}
The output:
Date 4/13/2015 = 38392503347
Date 6/13/2015 = 36229156954
Note that I added the date 6/13/2015 to your xml to have 2 different date
XML:
<Form1>
<Name Key="4/13/2015 6:31:26 AM">
<Date>4/13/2015</Date>
<JobNum>00000</JobNum>
<RevNum>00000</RevNum>
<Task>TimeStar</Task>
<Start>06:31 AM</Start>
<End>06:35 AM</End>
<TotalTime>2163346393</TotalTime>
</Name>
<Name Key="4/13/2015 6:35:11 AM">
<Date>4/13/2015</Date>
<JobNum>27163</JobNum>
<RevNum>00000</RevNum>
<Task>Redlines</Task>
<Start>06:35 AM</Start>
<End>07:35 AM</End>
<TotalTime>36229156954</TotalTime>
</Name>
<Name Key="6/13/2015 6:35:11 AM">
<Date>6/13/2015</Date>
<JobNum>27163</JobNum>
<RevNum>00000</RevNum>
<Task>Redlines</Task>
<Start>06:35 AM</Start>
<End>07:35 AM</End>
<TotalTime>36229156954</TotalTime>
</Name>
</Form1>

How to change an attribute in XML C#

I have tried several methods, none of which appear to work...
You can see the different methods I have tried by taking a look at the commented lines of code, but I am able to get the attribute fine, and newIndex is updated properly, but then when I go to change the attribute called count it doesn't do anything.
XmlElement reports = (XmlElement)doc.SelectSingleNode("//Reports");
XmlAttribute reportCount = (XmlAttribute)doc.SelectSingleNode("//Reports/#count");
int count = Convert.ToInt32(reportCount.Value);
newIndex = count + 1;
//doc.DocumentElement.SetAttribute("count", "\"" + newIndex.ToString() + "\"");
//reportCount.Value = newIndex.ToString();
reports.SetAttribute("count", newIndex.ToString());
XML File
<?xml version="1.0" encoding="utf-8"?>
<Reports count="1"><!--this count should be equal to the last id-->
<Report id="1">
<Workbook>APG0214.xlsx</Workbook>
<Filepath>\\fileserver\homeshares\POS Reports</Filepath>
</Report>
<Report id="2">
<Workbook>CBM0214.xlsx</Workbook>
<Filepath>\\fileserver\homeshares\POS Reports</Filepath>
</Report>
</Reports>
Any help is appreciated!
I'm not familiar with old XML API but I would use LINQ to XML in this case:
var xmlDocument = XDocument.Load("path");
var reports = xmlDocument.Root;
var maxId = reports
.Elements("Report")
.Select(x => (int)x.Attribute("id"))
.Max();
reports.Attribute("count").SetValue(maxId);
xmlDocument.Save("path");
You probably forgot about
doc.Save("your_path_to_xml_file")
at the end ;)
Just use the following:
reportCount.Value = newIndex.ToString(CultureInfo.InvariantCulture);
and the save the XML back to the original file (or somewhere new).

C# - How to split,replace the content of xml file?

I have a xml file:
<xml ?iwes sf>
<product>
<name> Computer </name>
<details>a product of Dell</details>
<sender> sender no name</sender>
</product>
</xml>
i want split to:
<xml ?iwes sf>, ,<product>, ,<name>,Computer,</name>,..., ,</xml>
Then i translate text content (Computer,a product of Dell, sender no name) to Korean Language.
Finally, i want join
<xml ?iwes sf>, ,<product>, ,<name>,Computer,</name>,..., ,</xml>
with result translated:
<xml ?iwes sf>
<product>
<name> 컴퓨터</name>
<details>Dell의 제품 </details>
<sender> 아니오 유명한 송신기 </sender>
</product>
</xml>
i used Regex:
string[] gettag = Regex.Split(inputText.Text, "(<.*?>)|(.+?(?=<|$))");
but it's wrong, it cann't do what i want, i cann't join xml tag to location before, cause it cann't get "\t"!
What should i do??
My English level is'ot good. I hope everyone can understand what i said and help me!
Thanks!
y not some lambda expression ?
you can try this.
IEnumerable<XElement> xx = xdoc.Root.Descendants().Elements().Where(c => { if (c.Name == "name") { c.Value = "Dell"; } else if (c.Name == "details") { c.Value = "Dell Detial"; } return true; }).Select(c => c);
// Loop.
string x = string.Empty;
foreach (XElement x1 in xx)
{
x += x1.ToString();
}
Console.WriteLine(x.ToString());

Parse XML Elements with LINQ

I have this xml.
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="el-gr" xmlns="http://www.w3.org/2005/Atom">
<title type="text">name.gr</title>
<updated>2011-07-23</updated>
<link href="link" />
<entry>
<title type="html">Οι επιθέσεις σε σκανδιναβικές χώρες</title>
<summary type="text">Η Νορβηγία, μία από τις σκανδιναβικές χώρες, έζησε μετά από πάρα πολλά χρόνια (2006) τον τρόμο. Δείτε αναλυτικά τις τελευταίες «τυφλές» επιθέσεις τα τελευταία χρόνια:...</summary>
<published>2011-07-23T12:54:00+03:00</published>
<link href="link" />
</entry>
i want to parse some of the elements inside . For that i use the following LINQ code.
var list = from y in xelement.Descendants("entry")
select new Update()
{
Title = y.Element("title").Value,
Pubdate = y.Element("published").Value,
Descr = y.Element("content").Value,
Link = y.Element("link").Attribute("href").Value
};
But it does not work. Can anyone tell me what am i doing wrong?
The nodes are all in the http://www.w3.org/2005/Atom namespace. Therefore you need to prefix the queries with this namespace, otherwise the query tries to find those elements in the empty namespace.
XNamespace atom = "http://www.w3.org/2005/Atom";
var list = from y in xelement.Descendants(atom+"entry")
select new Update()
{
Title = y.Element(atom+"title").Value,
Pubdate = y.Element(atom+"published").Value,
Descr = y.Element(atom+"content").Value,
Link = y.Element(atom+"link").Attribute("href").Value
};
In your XML example, there is missing "feed" endtag and you are using an element "content", but I guess "summary" is correct.

get this xml value with c#

I need to get the number next to the word text, in this case the number is 1
<SD>
<POPULARITY URL="google.com/" TEXT="1"/>
<REACH RANK="1"/>
<RANK DELTA="+0"/>
</SD>
How can I get the number in c#
Thanks
In addition to the examples above you could try using linq to xml
See below.
var str = #"<ALEXA VER='0.9' URL='google.com/' HOME='0' AID='='>
<SD TITLE='A' FLAGS='DMOZ' HOST='google.com'>
<TITLE TEXT='Google '/>
<ADDR STREET='' CITY='' STATE='' ZIP='' COUNTRY='' />
<CREATED DATE='15-Sep-1997' DAY='15' MONTH='09' YEAR='1997'/>
<PHONE NUMBER='unlisted'/>
<OWNER NAME='unlisted'/>
<EMAIL ADDR='dns-admin#google.com'/>
<LANG LEX='en'/>
<LINKSIN NUM='704402'/>
<SPEED TEXT='1581' PCT='48'/>
<REVIEWS AVG='4.5' NUM='524'/>
<CHILD SRATING='0'/>
<ASSOCS>
<ASSOC ID='googlecom'/></ASSOCS>
</SD>
<KEYWORDS>
<KEYWORD VAL='Mountain View'/>
</KEYWORDS><DMOZ>
<SITE BASE='google.com/' TITLE='Google' DESC='Enables users to search the Web, Usenet, and images. Features include PageRank, caching and translation of results, and an option to find similar pages. The companys focus is developing search technology.'>
<CATS>
<CAT ID='Top/Computers/Internet/Searching/Search_Engines/Google' TITLE='Search Engines/Google' CID='374822'/>
<CAT ID='Top/Regional/North_America/United_States/California/Localities/M/Mountain_View/Business_and_Economy/Industrial/Computers_and_Internet' TITLE='Industrial/Computers and Internet' CID='625367'/>
<CAT ID='Top/World/Arabic/إقليمـي/الشرق_الأوسط/السعودية/تجارة_و_أقتصاد/كمبيوتر_و_إنترنت/محركات_بحث' TITLE='كمبيوتر و إنترنت/محركات بحث' CID='204954'/>
<CAT ID='Top/World/Français/Informatique/Internet/Recherche/Moteurs_de_recherche/Google' TITLE='Moteurs de recherche/Google' CID='247347'/>
</CATS>
</SITE>
</DMOZ>
<SD>
<POPULARITY URL='google.com/' TEXT='1'/>
<REACH RANK='1'/>
<RANK DELTA='+0'/>
</SD>
</ALEXA>";
var item = XElement.Parse(str);
var subSet = item.Elements("SD");
var actualItem = subSet.Where(x => x.Element("POPULARITY") != null).First();
var value = actualItem.Element("POPULARITY").Attribute("TEXT").Value;
Hope this helps
Something like this:
XmlDocument doc = new XmlDocument();
doc.LoadXml( #"<SD> <POPULARITY URL=""google.com/"" TEXT=""1""/> <REACH RANK=""1""/> <RANK DELTA=""+0""/> </SD> ");
XmlNode root = doc.FirstChild;
Debug.WriteLine(root["POPULARITY"].Attributes["TEXT"].InnerXml);
You can try:
XmlDocument doc = new Xmldocument();
doc.Load(stringWithYourXml);
XmlNode node = doc.SelectSingleNode("/SD/POPULARITY");
var val = node.Attributes["TEXT"].Value
Please consider this as a sample ( do some more checks and error detection )

Categories

Resources