Replace element in xdocument placed in a treeview with another xelement - c#

I have a simple xmlfile and that is placed in a treeview
<bookstore xmlns="generic">
<book genre="Book" >`
<title>Book of Benjamin Franklin</title>
<author>
<first-name>Benson</first-name>
<last-name>Frank</last-name>
</author>
<price>89.88</price>
</book>
<book genre="autobiography">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Ben</first-name>
<middlename />
<last-name>Franklin</last-name>
</author>
<price>89.88</price>
</book>
<book genre="novel" >
<title>The Confidence Man</title>
<author>
<first-name>John</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
</bookstore>
I want to replace (2nd element)
<book genre="autobiography" >
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Ben</first-name>
<middlename />
<last-name>Franklin</last-name>
</author>
<price>89.88</price>
</book>
with an another element(that is edited and i have edited portion as a string)
<book genre="autobiography">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Ben</first-name>
<last-name>Franklin</last-name>
</author>
<price>89.88</price>
</book>
Code I used is here
XElement XmlTree = XElement.Parse(text);//text contain edited portion
XmlElement XMLE = (XmlElement)TreeV.SelectedItem;
XmlDocument xdoc = new XmlDocument();
xdoc.Load(scd_file);
XmlDocumentFragment xfrag = xdoc.CreateDocumentFragment();
xfrag.InnerXml = text;
XmlDocumentFragment xfrag1 = xdoc.CreateDocumentFragment();
xfrag1.InnerXml = XMLE.OuterXml;
xdoc.ReplaceChild(xfrag, xfrag1);
But it shows error (xfrag1 is not a node of xdoc)
please help me to solve this problem.

thank u all i got the solution.
XmlElement XMLE = (XmlElement)TreeV.SelectedItem;// selection from treeview(TreeV) that we want to edit (2nd element)
XmlDocument XD = new XmlDocument();
XD.LoadXml(text);// text is edited part save as a string
XmlNode root=XD.DocumentElement;
XmlDocument xml = XMLE.ParentNode.OwnerDocument;
XmlNode import= xml.ImportNode(root, true);
XMLE.ParentNode.ReplaceChild(import, XMLE);
xml.Save(scd_file); //scd_file path

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

Removing parent node from xml collections

I am trying to get rid of the parent node of a collection in xml (using linq-to-xml):
For example, the input xml:
<envelop>
<books>
<book>
<title>ABC</title>
<publishedDate>2012-12-12</publishedDate>
<authors>
<author>John Smith</author>
<author>Bob Doe</author>
</authors>
<book>
<book>
<title>XYZ</title>
<publishedDate>2013-03-06</publishedDate>
<authors>
<author>Henry Blah</author>
<author>Bob Doe</author>
</authors>
<book>
</books>
</envelop>
I would like the result to be:
<envelop>
<book>
<title>ABC</title>
<publishedDate>2012-12-12</publishedDate>
<author>John Smith</author>
<author>Bob Doe</author>
<book>
<book>
<title>XYZ</title>
<publishedDate>2013-03-06</publishedDate>
<author>Henry Blah</author>
<author>Bob Doe</author>
<book>
</envelop>
The nodes: <books> and <authors> are gone - only their children remain.
I saw the following question but with XSLT (Remove parent nodes from xml with xslt). Would like to stay away from XSLT at the moment.
var document = XDocument.Load(validXmlFilePath);
while (document.Descendants("authors").Any())
{
var x = document.Descendants("authors").First();
x.AddAfterSelf(x.Nodes());
x.Remove();
}
var result = document.Descendants("book");
Do you fill your object in code and than serialize it? If so, you can use [XmlElement("Book")] attribute above your list property in your class:
[XmlElement("Book")]
public List<Book> Books {get; set;}
In VB the code would be
Dim result As XElement = <envelop></envelop>
result.Add(xe...<book>)
For Each el As XElement In result...<author>.ToList
el.Parent.Parent.Add(New XElement(el))
Next
result...<authors>.Remove()
with xe defined as
Dim xe As XElement
'to load from a file
' xe = XElement.Load("Your Path Here")
' for testing
xe = <envelop>
<books>
<book>
<title>ABC</title>
<publishedDate>2012-12-12</publishedDate>
<authors>
<author>John Smith</author>
<author>Bob Doe</author>
</authors>
</book>
<book>
<title>XYZ</title>
<publishedDate>2013-03-06</publishedDate>
<authors>
<author>Henry Blah</author>
<author>Bob Doe</author>
</authors>
</book>
</books>
</envelop>
result looks like
<envelop>
<book>
<title>ABC</title>
<publishedDate>2012-12-12</publishedDate>
<author>John Smith</author>
<author>Bob Doe</author>
</book>
<book>
<title>XYZ</title>
<publishedDate>2013-03-06</publishedDate>
<author>Henry Blah</author>
<author>Bob Doe</author>
</book>
</envelop>

XML Parsing in windows phone

I have to parse XML,for that have used some code that's working but problem is not we have nested XML this code is unable to parse all data.So please suggest me how to part this.
XML
<Author>
<Book id="101" name="Computer" subcategories="2">
<Book id="600" name="java" subcategories="0" contents="10 books"/>
<Book id="601" name="php" subcategories="0" contents="5 books"/>
</Book>
<Book id="201" name="Language" subcategories="2">
<Book id="700" name="Hindi" subcategories="0" contents="6 books"/>
<Book id="701" name="English" subcategories="0" contents="4 books"/>
</Book>
<Book id="301" name="Music" subcategories="2">
<Book id="800" name="life" subcategories="0" contents="10 books"/>
<Book id="801" name="Wild" subcategories="0" contents="5 books"/>
</Book>
<Book id="401" name="Story" subcategories="2">
<Book id="900" name="My Life" subcategories="0" contents="1 books"/>
<Book id="901" name="One Day" subcategories="0" contents="1 books"/>
</Book>
</Author>
Parser method:
public void parser()
{
XElement nodes = XElement.Load("file.xml");
var node = from nd in nodes.DescendantNodes() select nd;
foreach (XElement nds in node)
{
string name = nds.Attribute("name").Value;
int id=Convert.ToInt32(nds.Attribute("id").Value);
MessageBox.Show("" + name);
MessageBox.Show("" + id);
if (nds.HasElements)
{
getChild(nds.DescendantNodes(),id);
}
}
public void getChild(IEnumerable<XNode> node,int id)
{
foreach (XElement nds in node)
{
IEnumerable<XNode> nd=from list in nds.DescendantNodes() select list;
int temp = Convert.ToInt32(ids);
foreach (XElement ss in nd)
{
string name = ss.Attribute("name").Value;
MessageBox.Show("" + name);
}
if (nds.HasElements)
{
getChild(nds.DescendantNodes(),id);
}
}
}
I have above XML and have used above code for parse.
Perhaps you're looking for this:
XElement doc = XElement.Parse(#"<Author>
<Book id=""101"" name=""Computer"" subcategories=""2"">
<Book id=""600"" name=""java"" subcategories=""0"" contents=""10 books""/>
<Book id=""601"" name=""php"" subcategories=""0"" contents=""5 books""/>
</Book>
<Book id=""201"" name=""Language"" subcategories=""2"">
<Book id=""700"" name=""Hindi"" subcategories=""0"" contents=""6 books""/>
<Book id=""701"" name=""English"" subcategories=""0"" contents=""4 books""/>
</Book>
<Book id=""301"" name=""Music"" subcategories=""2"">
<Book id=""800"" name=""life"" subcategories=""0"" contents=""10 books""/>
<Book id=""801"" name=""Wild"" subcategories=""0"" contents=""5 books""/>
</Book>
<Book id=""401"" name=""Story"" subcategories=""2"">
<Book id=""900"" name=""My Life"" subcategories=""0"" contents=""1 books""/>
<Book id=""901"" name=""One Day"" subcategories=""0"" contents=""1 books""/>
</Book>
</Author>");
var query = doc.Descendants();
foreach(XElement ele in query){
Console.WriteLine(string.Format("Name: {0}\nValue: {1}\n",ele.Name.LocalName.ToString(),ele));
if (ele.HasAttributes){
var query1 = ele.Attributes();
foreach (XAttribute att in query1)
{
Console.WriteLine(string.Format("Attribute: {0}\nValue: {1}\n", att.Name.LocalName.ToString(), att.Value));
};
};
};

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.

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