Adding a node to XMl - c#

the XML
<bookstore xmlns="http://www.contoso.com/books"
xmlns:g="http://www.contoso.com/genre">
<book g:genre="novel" publicationdate="2010-03-01" ISBN="1-123456-15-0">
<title>61 Hours</title>
<author xmlns="http://www.contoso.com/author">
<first-name>Lee</first-name>
<last-name>Child</last-name>
</author>
<price>6.99</price>
</book>
<bookstore>
I need to add a book node to it.. My code reads like this
strpath = "C:\\BookStore.xml";
XmlDocument doc = new XmlDocument();
doc.Load(strpath);
XmlNode root = doc.DocumentElement;
XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace("b", "http://www.contoso.com/books");
nsMgr.AddNamespace("g", "http://www.contoso.com/genre");
nsMgr.AddNamespace("a", "http://www.contoso.com/author");
// Create a Book element and populate its attributes
System.Xml.XmlElement XmlElementbook = doc.CreateElement("book");
//create the three attributes to hold the values
XmlElementbook.SetAttribute("g:genre";"novel5");
XmlElementbook.SetAttribute("publicationdate", "2010-11-03");
XmlElementbook.SetAttribute("ISBN", "1-00000-00-00");
// Insert the new element into the XML tree
// Create a new XML element and populate its attributes
System.Xml.XmlElement myXmlElementTitle = doc.CreateElement("title");
myXmlElementTitle.InnerText = "TestBook";
// Insert the new element under the node we created
XmlElementbook.AppendChild(myXmlElementTitle);
System.Xml.XmlElement myXmlElementAuthor = doc.CreateElement("author");
myXmlElementAuthor.SetAttribute("xmlns", ("http://www.contoso.com/author"));
System.Xml.XmlElement myXmlElementFirstname = doc.CreateElement("first-name");
myXmlElementFirstname.InnerText = "Bikram";
myXmlElementAuthor.AppendChild(myXmlElementFirstname);
System.Xml.XmlElement myXmlElementLastname = doc.CreateElement("last-name");
myXmlElementLastname.InnerText = "Mann";
myXmlElementAuthor.AppendChild(myXmlElementLastname);
XmlElementbook.AppendChild(myXmlElementAuthor);
// Price
System.Xml.XmlElement myXmlElementPrice = doc.CreateElement("price");
myXmlElementPrice.InnerText = "2.99";
// Insert the new element under the node we created
XmlElementbook.AppendChild(myXmlElementPrice);
//append the whole node to file
doc.DocumentElement.AppendChild(XmlElementbook);
doc.Save("C:\\BookStore.xml");
The only thing is the New node that gets written looks like
<bookstore xmlns="http://www.contoso.com/books"
xmlns:g="http://www.contoso.com/genre">
<book g:genre="novel" publicationdate="2010-03-01" ISBN="1-123456-15-0">
<title>61 Hours</title>
<author xmlns="http://www.contoso.com/author">
<first-name>Lee</first-name>
<last-name>Child</last-name>
</author>
<price>6.99</price>
</book>
***<book genre="novel5"
publicationdate="2010-11-03"
ISBN="1-00000-00-00"
xmlns="">
<title>TestBook</title>
<author xmlns="http://www.contoso.com/author">
<first-name>Bikram</first-name>
<last-name>Mann</last-name>
</author>
<price>2.99</price>
</book>***
<bookstore>
It has an extra XMLNS="" and g: is missing in the node
What Am i doing Wrong Please...

You want:
System.Xml.XmlElement XmlElementbook =
doc.CreateElement("book","http://www.contoso.com/books");
and
XmlElementbook.SetAttribute("genre","http://www.contoso.com/genre","novel5");
to create these nodes in the correct namespaces.

Related

Getting the XmlNode value for each xml node

I am using the below xml file
<?xml version="1.0" encoding="UTF-8"?>
<bookstore xmlns="urn:newbooks-schema">
<book>
<title>Books</title>
<price>20.00</price>
<attribute>
<fieldName>Books</fieldName>
<attributeStyle>ValueSet</attributeStyle>
<valueset>
<id>Part 1</id>
<values>
<displayName>Lord of the Rings</displayName>
</values>
</valueset>
</attribute>
</book>
<book>
<title>Books</title>
<price>20.00</price>
<attribute>
<fieldName>Books</fieldName>
<valueset>
<id>Part 1</id>
<values>
<displayName>Harry Potter</displayName>
</values>
</valueset>
</attribute>
</book>
</bookstore>
I am trying to get each node "book" in an XMLNodeList and I am looping the nodes to get the individual data of the node "values". I have used the below code and tried to achieve it But the valuenodes is always returning both the values nodes i.e., Lord of the Rings and the Harry Potter together and not in each loop. I want to achieve it one by one in a loop and not all together.
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(text);
var root = xmlDocument.DocumentElement;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);
nsmgr.AddNamespace("bk", "urn:newbooks-schema");
XmlNodeList criterion = root.SelectNodes("bk:book[bk:title='Books']", nsmgr);
foreach (XmlNode criterionNode in criterion)
{
XmlNode xml = criterionNode.SelectSingleNode("//bk:valueset", nsmgr);
var valuesNodeExpression = "//bk:valueset/bk:values[../../bk:fieldName='Books']";
XmlNodeList valueNodes = criterionNode.SelectNodes(valuesNodeExpression, nsmgr);
}
I slightly refactored the code, giving more telling names to the variables.
// Here the previous code is unchanged.
var books = root.SelectNodes("bk:book[bk:title='Books']", nsmgr);
Console.WriteLine(books.Count);
foreach (XmlNode book in books)
{
var valueset = book.SelectSingleNode(".//bk:valueset", nsmgr);
var id = valueset.SelectSingleNode("./bk:id", nsmgr).InnerText;
var displayName = valueset.SelectSingleNode(".//bk:displayName", nsmgr).InnerText;
Console.WriteLine(id);
Console.WriteLine(displayName);
}

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

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

manipulation of xml using c#

If I want to add, update or delete node in the xml using c#, how can it be done? My xml is shown below. I dont want transactionID node. I want to add a node called <Transformation>XML</Transformation> after corelationID node.
<?xml version="1.0" ?>
<GovTalkMessage xmlns="http://www.govtalk.gov.uk/CM/envelope">
<EnvelopeVersion>2.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>HMRC-VAT-DEC</Class>
<Qualifier>poll</Qualifier>
<Function>submit</Function>
<TransactionID />
<CorrelationID>1B93D48C02D740C6B79DE68A27F3ADE5</CorrelationID>
<ResponseEndPoint PollInterval="10">https://secure.dev.gateway.gov.uk/poll</ResponseEndPoint>
<GatewayTimestamp>2011-04-05T07:41:43.018</GatewayTimestamp>
</MessageDetails>
<SenderDetails />
</Header>
<GovTalkDetails>
<Keys />
</GovTalkDetails>
<Body />
</GovTalkMessage>
The easiest thing to use would be LINQ to XML. For example:
XDocument doc = XDocument.Load("file.xml");
XNamespace ns = "http://www.govtalk.gov.uk/CM/envelope";
// Remove TransationID
XElement transactionElement = doc.Descendants(ns + "TransactionID").Single();
transactionElement.Remove();
// Add XML:
XElement correlationElement = doc.Descendants(ns + "CorrelectionID").Single();
XElement newElement = new XElement(ns + "XML");
correlationElement.AddAfterSelf(newElement);
// Save back
doc.Save("new-file.xml");
//Load the XML
XmlDocument documentXML = new XmlDocument();
documentXML.Load(Server.MapPath("AddDeleteUpdate.xml"));
XmlNamespaceManager xmlns = new XmlNamespaceManager(documentXML.NameTable);
xmlns.AddNamespace("bk", "http://www.govtalk.gov.uk/CM/envelope");
//Identify the parent node i.e <MessageDetails>
XmlNode nodeMessage = documentXML.SelectSingleNode("//bk:GovTalkMessage/bk:Header/bk:MessageDetails", xmlns);
//Delete the node.
XmlNode nodeTransactionID = documentXML.SelectSingleNode("//bk:GovTalkMessage/bk:Header/bk:MessageDetails/bk:TransactionID", xmlns);
nodeMessage.RemoveChild(nodeTransactionID);
//Create the new XML noded to be added.
XmlNode controlAttrNode = null;
controlAttrNode = documentXML.CreateElement("Transformation");
controlAttrNode.InnerText = "XML";
controlAttrNode.Attributes.RemoveAll();
//Get the node object to where it need to be added.
XmlNode nodeCorrelation = documentXML.SelectSingleNode("//bk:GovTalkMessage/bk:Header/bk:MessageDetails/bk:CorrelationID", xmlns);
//Insert the node after.
nodeMessage.InsertAfter(controlAttrNode, nodeCorrelation);
documentXML.Save(Server.MapPath("AddDeleteUpdate.xml"));
You'll need
XMLNode.InsertAfter(newChildNode,referenceChildNode)
This should kickstart you:
http://msdn.microsoft.com/en-US/library/system.xml.xmlnode.insertafter%28v=VS.80%29.aspx

XML Parsing in C#

I want add the new node as parent node of the old nodes in XML using C#. for example node have the following XMl file:
<bookstore>
<books>
<author>
</author>
</books>
</bookstore>
like that now I want add the new like below:
<bookstore>
<newnode>
<books>
<author>
</author>
</books>
</newnode>
</bookstore>
Try this:-
XmlDocument doc = new XmlDocument();
doc.Load("BookStore.xml");
XmlElement newNode = doc.CreateElement("newnode");
doc.DocumentElement.AppendChild(newNode);
newNode.AppendChild(doc.SelectSingleNode("/bookstore/books"));
doc.Save("BookStore.xml");
Don't have VS here so can't confirm that this works but something like this:
XmlDocument xd = new XmlDocument();
xd.Load("oldxmlfile.xml");
XmlNode oldNode = xd["nameOfRootNode"];
xd.RemoveAll();
XmlNode newParent = xd.CreateNode("nodename");
newParent.AppendChild(oldNode);
xd.AppendChild(newParent);
xd.Save("newXmlFile.xml");
You can clone the old node, append the clone, and remove the original:
(edit; I forgot that AppendChild will move the node if it is already there... no need to clone and remove...)
XmlDocument doc = new XmlDocument();
// load the current xml
doc.LoadXml(xml);
// create a new "newnode" node and add it into the tree
XmlElement newnode = (XmlElement) doc.DocumentElement.AppendChild(doc.CreateElement("newnode"));
// locate the original "books" node and move it
newnode.AppendChild(doc.SelectSingleNode("/bookstore/books"));
// show the result
Console.WriteLine(doc.OuterXml);

Categories

Resources