C# How to extract complete xml node set - c#

<?xml version="1.0" encoding="ISO-8859-1"?>
<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">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.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>
Is their any way using XPath to select the complete first node set, for example from
<book category="COOKING">
to
</book>,
so that, that chunk of xml can be stored for later use.
Bob.

Let's say this XML is stored in an XmlDocument called doc.
XmlElement docRoot = doc.DocumentElement;
XmlNode cookingNode = docRoot.SelectSingleNode("./book[#category='COOKING']");
I tested this and added this line to verify:
Console.WriteLine(cookingNode.OuterXml);
Here was the output:
<book category="COOKING"><title lang="en">Everyday Italian</title><author>Giada
De Laurentiis</author><year>2005</year><price>30.00</price></book>

This query will select that node. Are you trying to get a set of nodes or just the single one? You might have to put the bookstore node back yourself if you only want th subset of nodes.
/bookstore/book[#category='COOKING']
as XmlDocument ...
var x = new XmlDocument();
x.Load("XmlFile1.xml");
var ns = x.SelectSingleNode("/bookstore/book[#category='COOKING']");
var res = ns.OuterXml;
as XDocument ...
var x = XDocument.Load("XmlFile1.xml");
var root = new XElement("bookstore",
from book in x.Element("bookstore").Elements("book")
where book.Attribute("category").Value == "COOKING"
select book
);
if you just want the book node you can do this instead of the root version above
var book = x.Element("bookstore")
.Elements("book")
.Where(n => n.Attribute("category").Value == "COOKING")
.First();

suppose I want to extract only the data wherethe xml file is as follows ..
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author auth="up">Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
the final result on the list view should look like this
lang auth
en up
I have coded as follows ..
XmlNodeList elemList = doc.GetElementsByTagName("book");
for (int j = 0; j < elemList.Count; j++)
{
if (elemList[j].Attributes["category"].Value == "COOKING")
{
XmlNodeList elemList1 = doc.GetElementsByTagName("author");
for (int i = 0; i < elemList1.Count; i++)
{
string attrVal = elemList1[i].Attributes["lang"].Value;
string attrVal1 = elemList1[i].Attributes["auth"].Value;
ListViewItem lvi = new ListViewItem();
lvi.SubItems.Add(attrVal1);
lvi.SubItems.Add(attrVal1);
}
listView1.Items.Add(lvi);
}
}
}

Adding to Matthew's response:
XmlDocument xDoc = new XmlDocument();
// (Put code to populate xDoc here)
XmlNodeList xNode = xDoc.SelectNodes(#"/bookstore/book[#category='COOKING']");
xNode now equals Book of type COOKING.

Related

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.

Get XML content from XmlNodeList

I have a question that may seem very simple, but it's giving me a headache. I have this XML file that has multiple entries, like:
<books>
<book>
<id>1</id>
<firstCover>
<author name="**" age="**" />
<title name="zz" font="yyy" size="uuu"/>
</firstCover>
<lastCover>
</lastCover>
</book>
<book>
<id>2</id>
<firstCover>
<author name="**" age="**" />
<title name="zz" font="yyy" size="uuu"/>
</firstCover>
<lastCover>
</lastCover>
</book>
</books>
Now, in order to get the XML content for first cover of book with id=1, I do this:
XmlNodeList b = root.SelectNodes("/books/book[contains(id,1)]/firstCover");
Then I would really need to take the whole content of what's inside the firstCover for that book :
<author name="**" age="**" />
<title name="zz" font="yyy" size="uuu"/>
and insert it into an XmlElement. This is where I'm stucked. I know I can do it with a foreach loop in XmlNodeList, but is there a more simple way?
I'm guessing you want to actually insert it into an XMLElement in another XMLDocument.
Is this what you are looking for?
XmlDocument sourceDoc = new XmlDocument();
//This is loading the XML you present in your Question.
sourceDoc.LoadXml(xmlcopier.Properties.Resources.data);
XmlElement root = sourceDoc.DocumentElement;
XmlElement b = (XmlElement)root.SelectSingleNode("/books/book[contains(id,1)]/firstCover");
XmlDocument destDoc = new XmlDocument();
XmlElement destRoot = destDoc.CreateElement("base");
destDoc.AppendChild(destRoot);
XmlElement result = destDoc.CreateElement("firstCover");
result.InnerXml = b.InnerXml;
destRoot.AppendChild(result);
destDoc.Save("c:\\test.xml");

Reading XML file in C# with XpathNavigator

I am trying to read the book.xml file provided as an example on the MSDN website.
<?xml version="1.0" encoding="utf-8" ?>
<bookstore>
<book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
<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 genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
<book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
<title>The Gorgias</title>
<author>
<name>Plato</name>
</author>
<price>9.99</price>
</book>
</bookstore>
I have the following code until now:
static void Main()
{
XmlDocument document = new XmlDocument();
document.Load(#"c:\books.xml");
XPathNavigator navigator = document.CreateNavigator();
XPathNodeIterator nodes = navigator.Select("/bookstore/book");
while (nodes.MoveNext())
{
Console.WriteLine(nodes.Current.HasAttributes);
}
}
It seems this code is reading everything, but from here on if I want to display, say, just the titles of all book etc., how do I access them?
You can iterate over the titles if you change the XPath expression to select all title nodes:
XPathDocument document = new XPathDocument(#"c:\tmp\smpl5.xml");
XPathNavigator navigator = document.CreateNavigator();
XPathNodeIterator nodes = navigator.Select("/bookstore/book/title");
foreach (XPathNavigator item in nodes)
{
Console.WriteLine(item.Value);
}
Note that you don't need to create an XmlDocument if you don't plan to modify the document. Using an XPathDocument is usually more light-weight.
you can also use this "//title" instead of "/bookstore/book"

Categories

Resources