Get entire node XML rather than InnerXml - c#

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

Related

insert xml tag with c#

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

how do i create and insert a node inside another node

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

XMLNodeList not retrieving right Nodes

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) {
...

Xpath path not working

I'm trying to get an element and its siblings via XpathNavigator.
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE document SYSTEM 'xmlschemas/domino_6_5_5.dtd'>
<document xmlns='http://www.lotus.com/dxl' version='6.5' maintenanceversion='5.0'>
<item name='Keywords'><text/></item>
<item name='Version'><number>1</number></item>
<item name='UPDATEDISTRIBUTION'><text>1</text></item>
<item name='$FILE' summary='true' sign='true' seal='true'>
<object>
<file hosttype='cdstorage' compression='none' flags='storedindoc' name='STG08828'>
<created><datetime>20110119T230442,22+01</datetime></created>
</file>
</object>
</item>
</document>
I want to navigate to the file-element, with the following XPath:
//item/name/object/file[#name='STG08828']
Why this path is wrong?
EDIT: Thanks for the hint with my "name"-mistake.
When I try to run it, I get nothing.
XmlElement rootNode = xmlDoc.DocumentElement;
// select the file Element
String query = "//file[#name='" + name + "']";
XmlNodeList fileElement = rootNode.SelectNodes(query);
I think you want:
//item/object/file[#name='STG08828']
Or maybe just:
//file[#name='STG08828']
I think you are missing your names space for xmlns='http://www.lotus.com/dxl'
Example:
XNamespace myMs = "http://www.lotus.com/dxl";

XML : merging xml file into nodes of another xml file

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

Categories