C# remove attribute from root node - c#

I tries to parse a XML file (get it from Dependacy Graph in VS 2012).
Here is sample of my .xml file
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="#101" Category="CodeSchema_ProjectItem" FilePath="$(ProgramFiles)\windows kits\8.0\include\um\unknwnbase.h" Label="unknwnbase.h" />
<Node Id="#103" Category="CodeSchema_ProjectItem" FilePath="$(ProgramFiles)\windows kits\8.0\include\shared\wtypesbase.h" Label="wtypesbase.h" />
in here, I needs to remove attribute "xmlns" from DirectedGraph.
here's my source to remove this
XmlNodeList rootNode = xmlDoc.GetElementsByTagName("DirectedGraph");
foreach (XmlNode node in rootNode)
{
node.Attributes.RemoveNamedItem("xmlns");
}
but this code doesn't work. If I don't delete this I can't select node like
XmlNodeList nodes = xmlDoc.DocumentElement.SelectNodes("/DirectedGraph/Nodes/Node");
What should I do?

If you like you can work with the namespace instead of removing the declaration:
var xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<DirectedGraph xmlns=""http://schemas.microsoft.com/vs/2009/dgml"">
<Nodes>
<Node Id=""#101"" Category=""CodeSchema_ProjectItem"" FilePath=""$(ProgramFiles)\windows kits\8.0\include\um\unknwnbase.h"" Label=""unknwnbase.h"" />
<Node Id=""#103"" Category=""CodeSchema_ProjectItem"" FilePath=""$(ProgramFiles)\windows kits\8.0\include\shared\wtypesbase.h"" Label=""wtypesbase.h"" />
</Nodes>
</DirectedGraph>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("d", "http://schemas.microsoft.com/vs/2009/dgml");
var nodes = doc.DocumentElement.SelectNodes("/d:DirectedGraph/d:Nodes/d:Node", manager);
Console.WriteLine(nodes.Count);

Use:
private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
if (!xmlDocument.HasElements)
{
XElement xElement = new XElement(xmlDocument.Name.LocalName);
xElement.Value = xmlDocument.Value;
foreach (XAttribute attribute in xmlDocument.Attributes())
xElement.Add(attribute);
return xElement;
}
return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
}
Taken from: How to remove all namespaces from XML with C#?.
You might also want to check out: XmlSerializer: remove unnecessary xsi and xsd namespaces.

Related

Remove an item from XML file using C#

I'm trying to write and remove items (categories) that I've stored in an XML file. I've figured out how to add using new XElement and doc.Root.Add but I don't know how to remove and item that has the same title as the input.
XML:
<?xml version="1.0" encoding="utf-8"?>
<categories>
<category title="Horror"></category>
<category title="Romance"></category>
<category title="Health"></category>
<category title="SciFi"></category>
<category title="Programming" />
<category title="History" />
</categories>
C#:
public static void RemoveFromCategoryXMLFile(string title)
{
XmlDocument doc = new XmlDocument();
doc.Load("../../DAL/XML_Categories/Categories.xml");
XmlNode node = doc.SelectSingleNode($"/categories/category[#name='{title}']");
if (node != null)
{
XmlNode parent = node.ParentNode;
parent.RemoveChild(node);
doc.Save("../../DAL/XML_Categories/Categories.xml");
}
}
I want the item that matches the string title to be removed from the document. Right now nothing happens and it seems like the XmlNode returns null.
Using XDocument is recommended, as it is a newer class for parsing XML. With such class it's enought to use such code:
var title = "Horror";
var xml = XDocument.Load(#"path to XML");
xml.Root.Elements("category").Where(e => e.Attribute("title").Value == title).Remove();
xml.Save(#"path to output XML");

Trying to change a XML node with no success

I'm trying to change a the value for the model atribute from the following .xml file.
<MTConnectDevices xmlns="urn:mtconnect.org:MTConnectDevices:1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mtconnect.org:MTConnectDevices:1.1 http://www.mtconnect.org/schemas/MTConnectDevices_1.1.xsd">
<Header version="1.1" sender="Company MTConnect Instance" creationTime="2010-08-26T19:00:47-07:00" instanceId="2" bufferSize="131072" />
<Devices>
<Device name="XX" iso841Class="1" uuid="000" id="id1001">
<Description manufacturer="name" serialNumber="Serial Number" model="UNDEFINED">
</Description>
This is what I've tried but it's not working as it's not changing the value for model.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(mypath);
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
var node = xmlDoc.SelectSingleNode("/ns:MTConnectDevices/ns:Header/ns:Devices/ns:Device/ns:Description", nsmgr);
node.Attributes["model"].Value = "changed";
xmlDoc.Save(mypath);
Can anyone give me a hand and tell me how to fix this?
Your xml contains namespaces, so you have to use them while retrieving node.
It can be done something like this:
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
var node = xmlDoc.SelectSingleNode("/ns:MTConnectDevices/ns:Devices/ns:Device/ns:Description", nsmgr);

Get entire XML except root element

<Employees>
<Product_Name>
<hello1>product1</hello1>
<hello2>product2</hello2>
<hello3>product3</hello3>
<hello4>product4</hello4>
</Product_Name>
<product_Price>
<hello1>111</hello1>
<hello2>222</hello2>
<hello3>333</hello3>
<hello4>444</hello4>
</product_Price>
</Employees>
is it possible to convert the following XML to the XML shown below using C#. I tried using remove function but it didn't work. I also tried to get the value of root node. Didn't work
<Product_Name>
<hello1>product1</hello1>
<hello2>product2</hello2>
<hello3>product3</hello3>
<hello4>product4</hello4>
</Product_Name>
<product_Price>
<hello1>111</hello1>
<hello2>222</hello2>
<hello3>333</hello3>
<hello4>444</hello4>
</product_Price>
If you just want to fetch the inner xml,you can use the XmlReader's ReadInnerXml.The innerXML is fetched as a string(skipping the root node).
var xmlReader = XElement.Load("data.xml").CreateReader();
xmlReader.MoveToContent();
string innerXml = xmlReader.ReadInnerXml();
If you have access to Linq to XML, you should you XDocument.
caveat: I believe your xml is malformed - you should have something like:
<?xml version="1.0" encoding="utf-8"?>
Add the first xml tag to the xml.
string xml = #"<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Product_Name>
<hello1>product1</hello1>
<hello2>product2</hello2>
<hello3>product3</hello3>
<hello4>product4</hello4>
</Product_Name>
<product_Price>
<hello1>111</hello1>
<hello2>222</hello2>
<hello3>333</hello3>
<hello4>444</hello4>
</product_Price>
</Employees>";
XDocument xDoc = XDocument.Parse(xml);
// get the elements
var rootElements = xDoc.Root.Elements();
Alternatively, you can load the xml from a file:
XDocument xDoc = XDocument.Load("xmlFile.xml");
You can store it as XmlNodeList to be well-formed. Here's a working example of how to do it:
XmlDocument xml= new XmlDocument();
xml.LoadXml(#"<Employees>
<Product_Name>
<hello1>product1</hello1>
<hello2>product2</hello2>
<hello3>product3</hello3>
<hello4>product4</hello4>
</Product_Name>
<product_Price>
<hello1>111</hello1>
<hello2>222</hello2>
<hello3>333</hello3>
<hello4>444</hello4>
</product_Price>
</Employees>");
var nodeList = xml.SelectNodes("Employees");
foreach (XmlNode node in nodeList)
{
Console.WriteLine(node.InnerXml); //this will give you your desired result
}

Make XML in c# with namespaces

I need to generate XML in the following form:
<ns1:root xmlns:ns1="http://example.com/xmlns1" xmlns:ns2="http://example.com/xmlns2">
<ns2:item ns2:param="value" />
</ns1:root>
I use this code:
XmlDocument xDoc = new XmlDocument();
XmlElement xRootElement = (XmlElement)xDoc.AppendChild(xDoc.CreateElement("ns1:root"));
xRootElement.SetAttribute("xmlns:ns1", "http://example.com/xmlns1");
xRootElement.SetAttribute("xmlns:ns2", "http://example.com/xmlns2");
XmlElement xElement = (XmlElement)xRootElement.AppendChild(xDoc.CreateElement("ns2:item"));
xElement.SetAttribute("ns2:param", "value");
But the result is the following:
<root xmlns:ns1="http://example.com/xmlns1" xmlns:ns2="http://example.com/xmlns2">
<item param="value" />
</root>
Thanks for the advice.
XmlElement xElement = (XmlElement)xRootElement.AppendChild(xDoc.CreateElement("ns2:item", "http://example.com/xmlns2"));
Gave me:
<root xmlns:ns1="http://example.com/xmlns1" xmlns:ns2="http://example.com/xmlns2">
<ns2:item param="value" />
</root>
By the way, "ns2:param" is not necessary. XML attributes belong to the same namespace as the element.
Try this:
XmlDocument xDoc = new XmlDocument();
XmlElement xRootElement = (XmlElement)xDoc.AppendChild(xDoc.CreateElement("ns1:root"));
xRootElement.SetAttribute("xmlns:ns1", "http://example.com/xmlns1");
xRootElement.SetAttribute("xmlns:ns2", "http://example.com/xmlns2");
XmlElement xElement = (XmlElement)xRootElement.AppendChild(xDoc.CreateElement("item", "http://example.com/xmlns1"));
xElement.SetAttribute("param", "http://example.com/xmlns1", "value");

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

Categories

Resources