I'm trying to insert an xml node with another child xml node in an existing xmldocument in C#.
I've got an XML doc that looks like so:
<?xml version="1.0" encoding="utf-16"?>
<DictionarySerializer>
<item>
<key>statusCode</key>
<value>0</value>
</item>
<item>
<key>statusSeverity</key>
<value>INFO</value>
</item>
<item>
<key>statusMessage</key>
<value>Status OK</value>
</item>
<item>
<key>MerchantAccountNumber</key>
<value>9999999999</value>
</item>
<item>
<key>ReconBatchID</key>
<value>420150418 1Q02144266965047801046AUTO04</value>
</item>
<item>
<key>PaymentGroupingCode</key>
<value>3</value>
</item>
<item>
<key>responsePaymentStatus</key>
<value>Completed</value>
</item>
<item>
<key>TxnAuthorizationTime</key>
<value>2015-04-18T09:14:41</value>
</item>
<item>
<key>TxnAuthorizationStamp</key>
<value>1429348481</value>
</item>
<item>
<key>ClientTransID</key>
<value>aidjl79f</value>
</item>
</DictionarySerializer>
and I need to insert another node with a node and node at the bottom.
I have this so far:
XmlDocument xmlCustomValues = new XmlDocument();
xmlCustomValues.LoadXml(OldCustomValues);
XmlNode NodeItem = xmlCustomValues.SelectSingleNode("DictionarySerializer");
XmlNode NodeNewItem = xmlCustomValues.CreateNode(XmlNodeType.Element, "item", null);
XmlNode NodeNewKey = NodeNewItem.??????
but not sure how to create a node under NodeNewItem (there's no "CreateNode" method). Never done this before (obviously) and the syntax does not make sense to me.
here's an answer that worked (test code for XML doc above)
string OldCustomValues = this.txtInput.Text;
XmlDocument xmlCustomValues = new XmlDocument();
xmlCustomValues.LoadXml(OldCustomValues);
XmlNode NodeItem = xmlCustomValues.SelectSingleNode("DictionarySerializer");
XmlNode NodeNewItem = xmlCustomValues.CreateNode(XmlNodeType.Element, "item", null);
NodeItem.AppendChild(NodeNewItem);
XmlNode NodeNewKey = xmlCustomValues.CreateNode(XmlNodeType.Element, "key", null);
NodeNewKey.InnerText = "MyKey";
XmlNode NodeNewValue = xmlCustomValues.CreateNode(XmlNodeType.Element, "value", null);
NodeNewValue.InnerText = "MyValue";
NodeNewItem.AppendChild(NodeNewKey);
NodeNewItem.AppendChild(NodeNewValue);
this.txtOutput.Text = xmlCustomValues.OuterXml;
You have already created the node, u just need to append the node to the root
NodeItem.AppendChild(NodeNewItem);
Related
I'm trying to insert a XML tag in an existing xml-file. To insert an XML-Tag in C# is not really a problem, but my Problem is, that i need the new beginning-tag and the ending-tag on a certain place in that file ... can anybody help me ...
here an Example:
this is the xml-file before:
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<Item>
<ItemID>2711</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>1</ColorID>
</Item>
<Item>
<ItemID>64566</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>3</ColorID>
</Item>
</DocumentElement>
... this should be the new XML-file -> with the new tag "Inventory":
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<Inventory>
<Item>
<ItemID>2711</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>1</ColorID>
</Item>
<Item>
<ItemID>64566</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>3</ColorID>
</Item>
</Inventory>
</DocumentElement>
can anybody help me?
You can wrap the existing Items in a new XElement then replace the nodes on the original document:
XDocument doc = XDocument.Parse("<DocumentElement><Item><ItemID>2711</ItemID><ItemTypeID>P</ItemTypeID><ColorID>1</ColorID></Item><Item><ItemID>64566</ItemID><ItemTypeID>P</ItemTypeID><ColorID>3</ColorID></Item></DocumentElement>");
var items = doc.Descendants("Item");
XElement inventory = new XElement("Inventory");
inventory.Add(items);
doc.Root.ReplaceNodes(inventory);
//now you can save the XDocument to a file or whatever
Creates this:
<DocumentElement>
<Inventory>
<Item>
<ItemID>2711</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>1</ColorID>
</Item>
<Item>
<ItemID>64566</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>3</ColorID>
</Item>
</Inventory>
</DocumentElement>
If you have LINQPad you can run this script: http://share.linqpad.net/7c636x.linq
You can try this
var doc = XDocument.Load(file);
var characters = doc.Descendants("DocumentElement").FirstOrDefault();
if (characters != null)
{
XElement xe = new XElement("Inventory");
characters.Add(xe);
var oColl = doc.Descendants("Item");
xe.Add(oColl);
}
doc.Save(file);
I am creating application to make Mod Menu's for Modern Warfare 3 (XRPC). I am making it customisable with XML, i have created an Example XML.
<MenuFile>
<Credits>
<Author>Callum Carmicheal</Author>
<Name>Sample</Name>
<Version>0.1</Version>
</Credits>
<InfoBar>
<Text>Created by ..., Enjoy</Text>
</InfoBar>
<Menu>
<Main>
<Header>
<Name>Main Menu</Name>
</Header>
<Item>
<Name>Enable Cheats</Name>
<Function>
<Menu>Mods</Menu>
</Function>
<Ignore>false</Ignore>
</Item>
<Item>
<Name> </Name>
<Function> </Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
</Main>
<Mods>
<Header>
<Name>Mods</Name>
</Header>
<Item>
<Name>Enable Cheats</Name>
<Function>
<Dvar>sv_cheats 1</Dvar>
</Function>
<Ignore>false</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
<Item>
<Name></Name>
<Function></Function>
<Ignore>True</Ignore>
</Item>
</Mods>
</Menu>
</MenuFile>
This is the markup for the Menu's, i have created some c# Code
private void button1_Click(object sender, EventArgs e) {
XmlDocument xml = new XmlDocument();
xml.LoadXml(System.IO.File.ReadAllText("menu.xml")); // suppose that myXmlString contains "<Names>...</Names>"
XmlNode credits_author = xml.SelectSingleNode("/MenuFile/Credits/Author");
XmlNode credits_name = xml.SelectSingleNode("/MenuFile/Credits/Name");
XmlNode credits_version = xml.SelectSingleNode("/MenuFile/Credits/Version");
Log("Credits(Author): " + credits_author.InnerText);
Log("Credits(Name): " + credits_name.InnerText);
Log("Credits(Version): " + credits_version.InnerText);
XmlNode InfoBar = xml.SelectSingleNode("/MenuFile/InfoBar/Text");
Log("");
Log("InfoBar Text: " + InfoBar.InnerText);
Log("");
Log("Menus");
XmlNodeList Menus = xml.SelectNodes("/MenuFile/Menu");
// This returns
// /MenuFile/Menu not /MenuFile/Menu/MainMenu....
// it should loop through MainMenu, Mods...
foreach (XmlNode MenuItem in Menus) {
Log("\t Menu: " + MenuItem.Name); // Main should me MainMenu or Mods
XmlNodeList Items = xml.SelectNodes("/MenuFile/Menu/" + MenuItem.Name);
foreach (XmlNode mi in Items) {
if (mi.Name == "Header") {
string xpath = FindXPath(mi);
string Header = xml.SelectSingleNode("/MenuFile/Menu/" + MenuItem.Name + "/Header/Name").InnerText;
Log("\t\t Header: " + Header);
}
else if (mi.Name == "Item") {
string Name = "";
string ignore = "";
}
}
}
}
But the problem is when trying to retrieve the MenuList/Menu's children nodes, it returns MenuList/Menu itself i have no clue.
I've tried debugging but the results are the same, can anyone see my error in this?
Your problem is that you are looping through the Menu nodes, not Main or Mods nodes:
XmlNodeList Menus = xml.SelectNodes("/MenuFile/Menu");
foreach (XmlNode MenuItem in Menus) {
will always return the outer Menu nodes.
To fetch the Main/Mods nodes use the following:
XmlNodeList menus = xml.SelectNodes("/MenuFile/Menu/*");
foreach (XmlNode menuItem in menus) {
Also, rather just fetch 'Header' and 'Items' nodes directly rather than performing an unnecessary "if":
XmlNode headerItem = menuItem.SelectSingleNode("Header");
...
XmlNodeList items = menuItem.SelectNodes("Item");
foreach (XmlNode item in items) {
...
Given the following XML:
<Root>
<Item id="1">
<name>Foo</name>
<status>Active</status>
</Item>
<Item id="2">
<name>Bar</name>
<status>Inactive</status>
</Item>
</Root>
Let's say I have this XML in an XmlDocument object and then have the following code:
var nodes = xmlDocumentObject.GetElementsByTagName("Item");
foreach (var node in nodes)
{
var nodeXml = ??
}
I can easily get the InnerXml of each node, which for the first node would be:
<name>Foo</name>
<status>Active</status>
But how can I get the XML for the node including the containing tag and its attributes, such as this:
<Item id="1">
<name>Foo</name>
<status>Active</status>
</Item>
Try using XmlNode.OuterXml instead of InnerXml :
foreach (XmlNode node in nodes)
{
var nodeXml = node.OuterXml;
}
I have two XML files that I want to merge in first file’s nodes
First file
Toc.xml
<toc>
<item id ="c12">
<english>book1</english>
<french>book1</french>
</title>
</item>
<item id = "part1"/>
<item id = "part2"/>
<item id = "part3"/>
</toc>
Second file will be updated every time after running transformation with XML files(part 1,2,3)
Second file :while running transformation with part1.xml
<item id = “part 1”>
<title>
<english>part1</english>
<french>part1</french>
</title></item>
Second file :while running transformation with part2.xml
<item id = “part 2”>
<title>
<english>part2</english>
<french>part2</french>
</title>
</item>
Result in Toc file
<toc>
<item id ="c12">
<english>book1</english>
<french>book1</french>
</title>
</item>
<item id = "part1">
<title>
<english>part1</english>
<french>part1</french>
</title>
</item>
<item id = "part2">
<title>
<english>part2</english>
<french>part2</french>
</title>
</item>
<item id = "part3">
<title>
<english>part3</english>
<french>part3</french>
</title>
</item>
</toc>
I tried using import node but it gives me errors(root element is missing) and other error "The node to be inserted is from a different document context"
Here is the code i tried
XmlDocument temp = new XmlDocument();
temp.Load("secondfile.xml");
XmlDocument toc = new XmlDocument();
toc.Load(toc.xml);
XmlNodeList toclist = toc.SelectNodes("/toc/item");
foreach (XmlNode tocnode in toclist)
{XmlNodeList tempnodelist = temp.SelectNodes("/item");
foreach (XmlNode tempnode in tempnodelist)
{ XmlNode importnode = toc.ImportNode(tempnode, true);
toc.appendNode(importnode, tocnode);
}}
you are right. My question was not clear. i changed que to be more specific. i hope you will find it more clean this time.
Thank you.
<item id = “part 1”>
<title>
<english>part1</english>
<french>part1</french>
</title>
</item>
<toc>
<item id ="c12">
<english>book1</english>
<french>book1</french>
</item>
<item id = "part1"/>
<item id = "part2"/>
<item id = "part3"/>
</toc>
The answer might be:
XmlDocument mainDocument = new XmlDocument();
mainDocument.Load("toc.xml");
XmlDocument tempDocument = new XmlDocument();
tempDocument.Load("part1.xml");
XmlNodeList tempList = tempDocument.GetElementsByTagName("item");
string id=tempList[0].GetAttribute("id");//gets the id attribute value
XmlNode mainRoot = mainDocument.DocumentElement; //gets the root node of the main document toc.xml
XmlNodeList mainList = mainRoot.SelectNodes("/toc");
XmlNode itemNode = mainList.Item(0).SelectSingleNode(string.Format("/toc/item[#id=\"" + id + "\"]")); //select the item node according to the id attribute value
XmlNode tempitemNode = tempList.Item(0).SelectSingleNode(string.Format("/toc/item[#id=\"" + id + "\"]/title")); //select the title node of the part1, part2 or part3 files
itemNode.AppendChild(tempitemNode.FirstChild);
itemNode.AppendChild(tempitemNode.LastChild);
mainDocument.Save("toc.xml");
Something like that
I've figured out how to append nodes to my rss document in the right structyre. I now need to sort it in the pubDate order and then output to screen. Looking at the examples online, I've found lots of XDocument and Linq stuff but nothing with XmlDocument. Scratching my head whether to scrap what code I have and work out how to do it in XDocument with advice from here or continue with XMLDocument and figure out a way to sort.
With XMLDocument I've got the code working exactly as I want, just need my feed to be sorted in pubDate order when it spits it out to the screen. So I think I will stick with this for the timebeing. I've found this article http://support.microsoft.com/kb/555060 and an xslt someone posted in Stack Overflow, but I dont know how to call the "XmlHelperFunctions" from my code. Is XSLT the easiest option I have, or is there something easier out there?
This is my code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(rssFeed.ToString());
XmlNodeList nl = xmlDoc.SelectNodes("/rss/channel/item");
foreach (XmlNode xn in nl)
{
string title = xn["title"].InnerText;
string link = xn["link"].InnerText;
string desc = xn["description"].InnerText;
string auth = xn["author"].InnerText;
string pdate = xn["pubDate"].InnerText;
XmlElement itemnode = xmlDoc.CreateElement("item");
itemnode.InnerXml = "<title></title><link></link><description></description><author></author><pubDate></pubDate>";
itemnode["title"].InnerText = title;
itemnode["link"].InnerText = link;
itemnode["description"].InnerText = desc;
itemnode["author"].InnerText = auth;
itemnode["pubDate"].InnerText = pdate;
xmlDoc.DocumentElement.SelectNodes("/rss/channel")[0].AppendChild(itemnode);
}
// Output to screen
xmlDoc.Save(Response.Output);
my rss feed
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
<channel>
<title>My RSS Feed</title>
<link>http://www.mylink.aspx</link>
<description>
</description>
<item>
<title>Top marks</title>
<link>http://www.mymarks.aspx</link>
<description>
<p>description field here</p>
</description>
<author>Viv</author>
<pubDate>Thu, 16 Aug 2012 12:10:54 GMT</pubDate>
</item>
<item>
<title>Costa Coffee</title>
<link>http://www.Costa.aspx</link>
<description>
<p>Costa Coffee have special offers.</p>
</description>
<author>Mike</author>
<pubDate>Thu, 23 Aug 2012 15:55:53 GMT</pubDate>
</item>
<item>
<title>Celebrate success</title>
<link>http://www.Celebrate.aspx</link>
<description>
<p>Lets all celebrate </p>
</description>
<author>Viv</author>
<pubDate>Thu, 22 Aug 2012 09:10:21 GMT</pubDate>
</item>
</channel>
</rss>
You can do this fairly quickly and painlessly using Linq to XML.
If you parse your XML using XElement.Parse(...) you can then use OrderBy or OrderByDescending functions and alter the content pretty easily.
Here is a simplified example:
XElement element = XElement.Parse(#"
<rss>
<channel>
<item title='something' pubDate='22/11/2012'/>
<item title='something2' pubDate='24/03/2012'/>
<item title='something3' pubDate='10/02/2010'/>
<item title='something4' pubDate='22/01/2011'/>
</channel>
</rss>");
var elements = element.Element("channel")
.Elements("item")
.OrderBy<XElement, DateTime>(e => DateTime.ParseExact(e.Attribute("pubDate").Value, "dd/MM/yyyy", null))
.Select(e => new XElement("item",
new XElement("title", e.Attribute("title").Value),
new XElement("pubDate", e.Attribute("pubDate").Value))); // Do transform here.
element.Element("channel").ReplaceAll(elements);
Console.Write(element.ToString());
The XML is not going to be the same as yours, but hopefully it gives you an idea of what you could do. You can just specify XElement and XAttribute objects as content for your new XML, this outputs the following:
<rss>
<channel>
<item>
<title>something3</title>
<pubDate>10/02/2010</pubDate>
</item>
<item>
<title>something4</title>
<pubDate>22/01/2011</pubDate>
</item>
<item>
<title>something2</title>
<pubDate>24/03/2012</pubDate>
</item>
<item>
<title>something</title>
<pubDate>22/11/2012</pubDate>
</item>
</channel>
</rss>
I hope this is useful.