How can i get the parent of node text value in c#? - c#

I have the following xml:
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
</catalog>
I found the title named "Midnight Rain". Now i want to know who is his parent so that i can use the <author> text node. I tried something like:
var xpath = "../*[local-name() != 'title']";
xml.Load(xmlalltext);
var xl1 = xml.SelectNodes(xpath);
MessageBox.Show(xl1.Item(0).InnerText.ToString());

If you've already found the title node and you're looking for the parent node, you can just select the parent node of the current node.
var parentNode = titleNode.SelectSingleNode("..");
If you're looking for the author node:
var authorNode = titleNode.SelectSingleNode("../author");
Alternatively, you may look for preceding or following siblings:
var authorNode = titleNode.SelectSingleNode("following-sibling::author") ?? titleNode.SelectSingleNode("preceding-sibling::author");
Edit: To answer your comment, if you only have the string of the title, then you may use the following to get the author:
string xml = #"xml...";
var doc = XDocument.Parse(xml);
string author = doc
.Descendants("book")
.Where(x => x.Element("title").Value == "Midnight Rain")
.Select(x => x.Element("author").Value)
.FirstOrDefault();

using XLinq
sample.xml(in below snipped) contains xml data
XElement root = XElement.Parse(File.ReadAllText("sample.xml"));
var matchingBooks = root.Descendants().Where(i=>String.Equals(i.Value,"Midnight Rain")).Select(i=>i.Parent) ;
var authors = matchingBooks.Elements("author");
Output in LinqPad
matchingBooks.Dump();
authors.Dump();
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
<author>Ralls, Kim</author>

You can use this xpath expession to get author node
"/catalog/book[title='Midnight Rain']/author"
or this to get parent node
"/catalog/book[title='Midnight Rain']"
eg.
var result = xml.SelectNodes(string.Format("/catalog/book[title='{0}']/author", "Midnight Rain"))

Related

How to get part of a string from inside a node using c#

I have an xml file like
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide [49-o]</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at [41-p] creating applications with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect [100-x] battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.</description>
</book>
<book id="bk103">
<author>Corets, Eva</author>
<title>Maeve Ascendant</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-11-17</publish_date>
<description>After the collapse of a nanotechnology society in England, the [01-i] young survivors lay the foundation for a new society.</description>
</book>
</catalog>
How can use linq2xml to extract the values "[(\d+)-([a-z])]" from each of the nodes <description> and store it in a variable or maybe use it like add those extracted values to a new attribute of the respective nodes like <description val="41-p"> etc. ?
You could use Descendants
Regex regex = new Regex(#"(\d+)-([a-z])");
var xdoc = XDocument.Parse(xml);
var descriptions = xdoc.Descendants("description")
.Where(x => regex.Match(x.Value).Success)
.Select(x => regex.Match(x.Value).Value).ToList();
Output:
41-p
100-x
01-i
If you want to set extracted values as attribute;
Regex regex = new Regex(#"(\d+)-([a-z])");
var xdoc = XDocument.Parse(xml);
var descriptions = xdoc.Descendants("description")
.Where(x => regex.Match(x.Value).Success);
foreach (var description in descriptions)
{
var regexResult = regex.Match(description.Value).Value;
var attribute = new XAttribute("id", regexResult);
description.Add(attribute);
}
xdoc.Save("sample.xml");
I'm not familiar with linq2xml, so I'd use XmlDocument and XPath expressions to find the nodes I'm interested in. Something like this:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
var books = doc.SelectNodes("//catalog/book");
foreach (XmlNode book in books)
{
var description = book.SelectSingleNode("description");
Regex regex = new Regex(#"(\[.*\])");
var match = regex.Match(description.InnerText);
if (match.Success)
{
var val = match.Groups[0].Value;
var attribute = doc.CreateAttribute("val");
attribute.Value = val;
description.Attributes.SetNamedItem(attribute);
}
}
// Convert XmlDocument back to string
var stringWriter = new StringWriter();
var xmlTextWriter = XmlWriter.Create(stringWriter);
doc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
xmlString = stringWriter.GetStringBuilder().ToString();

printing list of xml nodes in c#

I am need bit of help on getting list of xml nodes and printing them.
My code is as below:
XmlDocument doc = new XmlDocument();
doc.Load("To44532.xml");
XmlNode xn = doc.DocumentElement;
foreach (XmlNode xn2 in xn)
{ Console.WriteLine(xn2); }
Console.ReadLine();
I am new to c# please accept my apologies in advance for asking this basic question. So I wanted full list of nodes and then printing them in output.
I ended up with this piece of code because I wanted to debug one of the other code. The idea was that I wanted to display specific nodes in winforms. I tried if statement e.g. :
foreach (XmlNode node in doc.DocumentElement)
{
if (node.Equals("DbtItm"))
{ ..... }
Could you please advise whats the best way to achieve it?
You can select XML Nodes by Name.
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
For example to get only book author and book year from as above xml.
XmlDocument xml = new XmlDocument();
xml.Load("XMLFile1.xml");
XmlNodeList xnList = xml.SelectNodes("/bookstore/book");
foreach (XmlNode xn in xnList)
{
string author = xn["author"].InnerText;
string year = xn["year"].InnerText;
Console.WriteLine(author+"-"+year);
}

Join two children

I have this XML File:
<library>
<book ISBN="BSWE153" authors = "AC532" >
<title>Leraing XML</title>
<year>1995</year>
<publisher>W3C</publisher>
</book>
<author id="AC532">
<firstName>Hamdy</firstName>
<middleName/>
<lastName>Taha</lastName>
<nationality>Egypatian</nationality>
</author>
</library>
How to print the information of a book (with its authors information) given by its ISBN?
You can do that using XDocument, for example. You will need to
Parse your string (or load the file)
locate the book
read author Id (or ids?)
locate the author
nicely format it all together - with appropriate checks.
that is just a sketch:
const string xml = #"<?xml version=""1.0""?>
<library>
<book ISBN=""BSWE153"" authors = ""AC532"" >
<title>Leraing XML</title>
<year>1995</year>
<publisher>W3C</publisher>
</book>
<author id=""AC532"">
<firstName>Hamdy</firstName>
<middleName/>
<lastName>Taha</lastName>
<nationality>Egypatian</nationality>
</author>
</library>
";
var doc = XDocument.Parse(xml);
var book = doc.Root.Elements("book")
.FirstOrDefault(b => (string)b.Attribute("ISBN") == "BSWE153" );
var authorId = book.Attribute("authors").Value.ToString();
var author = doc.Root.Elements("author")
.FirstOrDefault(b => (string)b.Attribute("id") == authorId );
Console.WriteLine("{0} by {1} {2}",
book.Element("title").Value,
author.Element("firstName").Value,
author.Element("lastName").Value);

How to get special data from xml file using c#

Hi all
I have a xml file:
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>30</price>
</book>
<book category="CHILDREN">
<title lang="en">abc</title>
<author>bcd</author>
<year>2006</year>
<price>29</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
How to I can get price list when category = "CHILDREN"? I using C#.
example: Output is : price of Harry Potter is 30 and price of abc is 29
Thank,
You can use LINQ to XML. Following code will return collection of anonymous type instances with all data from your XML:
var xDoc = XDocument.Load("Input.txt");
var books = xDoc.Root
.Elements("book")
.Where(b => (string)b.Attribute("category") == "CHILDREN")
.Select(b => new
{
Title = (string)b.Element("title"),
Author = (string)b.Element("author"),
Year = (int)b.Element("year"),
Price = (decimal)b.Element("price")
});
You can call .First() method on books to get only one/first found item.

Getting the previous node of a searched keyword in xml

I have an xml document like the following:
<bookstore>
<book>
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
<book>
<title>Zen and the Art of Motorcycle Maintenance</title>
<author>
<first-name>Robert</first-name>
<last-name>Pirsig</last-name>
</author>
<price>5.99</price>
</book>
<book>
<title>Other Cities</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Rosenbaum</last-name>
</author>
<price>9.99</price>
</book>
</bookstore>
Of course, the bookstore has more than one book, so I I want to search for an author and then get returned an XElement for the book node that contains the searched author name.
var document = XDocument.Parse(xml);
var bookElements = document.Descendants("book")
.Where(arg => arg.Element("author").Element("first-name").Value == "Benjamin")
.ToList();
or
var bookElements = document.Descendants("first-name")
.Where(arg => arg.Value == "Benjamin")
.Select(arg => arg.Parent.Parent)
.ToList();
[Edit] As you keep editing the question, I will edit the answer :).
To find the first book that meets the criteria:
var foundBookElement = document.Descendants("book")
.Where(arg => arg.Element("author").Element("first-name").Value == "Benjamin")
.FirstOrDefault();
foundBookElement will be null if none of the books match the criteria.

Categories

Resources