I try to remove some XmlElements from my Xml file in C#2.0.
I can remove it successfully with XmlNode.Remove() method. But there is no Remove method in XmlElement.
I googled and found this.
elements are a type of node. In fact, if you look at the members of XmlNode and XmlElement in the .NET Framework, you will see that they are very much alike, but XmlElement has more going on. It inherits XmlNode and then is further customized. This is because an element is more specialized. A node is more general in scope. The document is a node, a processing instruction is a node, and so forth. Elements are different. If you look at the XmlNodeType property of an element, you will see that it is Element, one of the many types of nodes you find.
If element are a type of node, then why I can't use remove command. Then how?
XmlDocument doc_AlarmSettingUp = new XmlDocument();
doc_AlarmSettingUp.Load(xmlFile_AlarmSettingUp);
XmlNode rootDest = doc_AlarmSettingUp.SelectSingleNode("/Equipment/AlarmSettingUp/EnabledALIDs");
foreach (XmlElement el_AlarmSettingUp in doc_AlarmSettingUp.SelectNodes("/Equipment/AlarmSettingUp/EnabledALIDs/ALID"))
{
XmlElement outEl;
if (lookup.TryGetValue(el_AlarmSettingUp.GetAttribute("alid"), out outEl))
{
// exists; element now in "other"
// Console.WriteLine("exists");
}
else
{
// doesn't exist
Console.WriteLine("doesn't exist");
// Then How can I remove element with an element method? Thanks.
}
}
The following code should work on any XmlElement:
if (outEl.ParentNode != null) outEl.ParentNode.RemoveChild(outEl);
What are you trying to do with the code above? It doesn't relate to the question as far as I can see.
What is the problem with calling Remove on an XmlElement (which is an XmlNode)?
As far as I can see, XmlNode doesn't have a Remove() method either. It does have a RemoveChild(XmlNode) method, and so does XmlElement. You should use RemoveChild of the parent element to remove the child element.
Related
I have a xml like below
<ProcessInvoice>
<ApplicationArea>
<CreationDateTime>2016-06-01 13:15:36</CreationDateTime>
<ApplicationGroup>BBEX</ApplicationGroup>
<MessageType>PROCESSINVOICE</MessageType>
</ApplicationArea>
</ProcessInvoice>
Now I have path and value to add, but it is dynamic.
It can be like following
path-/ProcessInvoice/ApplicationArea/UserArea/Sample1
value-001
path-/ProcessInvoice/ApplicationArea/UserArea/UserAreaLine/Sample1
value-002
if the path is present then i have to add the value, else modify the value.
I can split the path and loop through to find till what node is present and what i have to add but I think there might be more elegant way of doing this.Please help me with the best approach to solve this?
Edit
Note- I will prefer XDocument And XElement.
May be I didnt explain properly.
My xml and node path both are dynamic.
There might be situation where multiple nodes are missing from my xml.
Now problem is i need to identify upto which node is existing in xml and which nodes i need to create.
Thanks
If "Sample1" node always exist, the code will look like this:
XmlDocument doc = new XmlDocument();
doc.Load(FILE);
var userArea = DocumentElement["ProcessInvoice"]["ApplicationArea"]["UserArea"];
foreach (XmlNode element in userArea.ChildNodes)
{
if (element.Name== "Sample1" )
{
XmlNode node == element;
node.InnerText ="001";
}
else if (element.Name == "UserAreaLine")
{
XmlNode node == element["Sample1"];
node.InnerText ="002";
}
}
<Block ID="Ar0010100" BOX="185 211 825 278" ELEMENT_TYPE="h1" SEQ_NO="0" />
This is an example from my XML code. In C# I need to store ONLY ID'S inside of a block element in one variable, and ONLY Box's inside of a block element. I have been trying to do this for two days, and I don't know how to narrow down my question.
XmlNodeList idList = doc.SelectNodes("/Block/ID");
doesn't work... Any version of doc.selectnode, doc.GetElementBy... doesn't return the right element/children/whatever you call it. I'm not able to find documentation that tells me what I'm trying to reference. i don't know if ID or BOX are children, if they're attributes or what. This is my first time using XML, and I can't seem to narrow down my problem.
You can simply use following code
XmlNodeList elemList = doc.GetElementsByTagName("Your Element");
for (int i = 0; i < elemList.Count; i++)
{
string attrVal = elemList[i].Attributes["ID"].Value;
}
Demo: https://dotnetfiddle.net/5PpNPk
the above code is taken from here Read XML Attribute using XmlDocument
The problem is that ID is actually neither child nor part.
It's a node's attribute. You can access it this way:
doc.SelectSingleNode("/Block").GetAttribute("ID")
// or
doc.SelectSingleNode("/Block").Attributes["ID"].Value
Of course, you can iterate through them:
foreach (XmlElement element in doc.SelectNodes("/Block"))
{
Console.WriteLine(element.GetAttribute("ID"));
}
You also can ensure that it contains ID attribute, so, you won't get NullReferenceException or other exception. Use the following XPath:
foreach (XmlElement element in doc.SelectNodes("/Block[#ID]"))
{
Console.WriteLine(element.GetAttribute("ID"));
}
Your attempted xpath tried to find <Block> element having child element <ID>. In xpath, you use # at the beginning of attribute name to reference an attribute, for example /Block/#ID.
Given a correct xpath expression as parameter, SelectNodes() and SelectSingleNode() are capable of returning attributes. Here is an example :
var xml = #"<Block ID=""Ar0010100"" BOX=""185 211 825 278"" ELEMENT_TYPE=""h1"" SEQ_NO=""0"" />";
var doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeList idList = doc.SelectNodes("/Block/#ID");
foreach(XmlNode id in idList)
{
Console.WriteLine(id.Value);
}
Demo
I need some help in returning an XmlDocument object from XPathNodeIterator.
Here is what I was trying to do:
public XmlDocument GetFilteredXML(XmlDocument baseXML, int codeID)
{
XPathNavigator nav = baseXML.CreateNavigator();
string xpath = /*some expression based on codeID*/;
XPathExpression exp = nav.Compile(xpath);
exp.AddSort(/*do some sorting*/);
XPathNodeIterator iter = exp.Select(exp);
// Here how do I return an XmlDocument object from
// the iterator which contains the selected nodes only?
}
The XPathNodeIterator does not contain the nodes, exactly. The name is a clue - it is an iterator, which means it only contains the logic for how to iterate over the nodes you want. The nodes themselves come from somewhere else - in this case, the original baseXML object you provided. They never leave that object, you just created a navigator that knows how to navigate the document, and an iterator, which knows how to iterate the navigator using some criteria.
To do what you're describing, you need to create a new XmlDocument, give it a new root element, and for each node from the iterator, call ImportNode and then Append. This will create a flat XmlDocument with all the selected nodes in the root element.
This is an option:
if (iter.MoveNext()) // Position on first node selected,
{ // assuming that it is the container for the desired result.
XmlDocument output = new XmlDocument();
output.LoadXml(iter.Current.OuterXml);
return output;
}
However, I don't think you need to make it into an XPathNavigator in the first place. What operation are you doing, that cannot be accomplished using the XmlDocument methods ?(SelectNodes and SelectSingleNode springs to mind for evaluating an XPath expression)
I have a simple function that's designed to copy a section of an xml document to another. I want to replace one node with the other so ReplaceChild seems like the logical choice. I keep getting the error 'The reference node is not a child of this node.' though. That seems odd since I found that node by asking for the parent in the first place. Any idea what I'm doing wrong?
private static void KeepSection(XmlDocument newDoc, XmlDocument currentDoc, XmlNamespaceManager nsmgr, string path)
{
XmlNode section = currentDoc.SelectSingleNode(path, nsmgr);
XmlNode newSection = newDoc.SelectSingleNode(path, nsmgr);
if (newSection != null && section != null)
{
XmlNode parent = newSection.ParentNode;
parent.ReplaceChild(newSection, newDoc.ImportNode(section, true));
}
}
It looks like you have your ReplaceChild parameters reversed:
public virtual XmlNode ReplaceChild(
XmlNode newChild,
XmlNode oldChild
)
Actually I was being an idiot. I got the parameters to ReplaceChild the wrong way around. The code should have been,
parent.ReplaceChild(newDoc.ImportNode(section, true), newSection);
Sorry about that!
I have two XmlDocuments. Something like:
<document1>
<inner />
</document1>
and
<document2>
<stuff/>
</document2>
I want to put document2 inside of the inner node of document1 so that I end up with a single docement containing:
<document1>
<inner>
<document2>
<stuff/>
</document2>
</inner>
</document1>
Here's the code...
XmlDocument document1, document2;
// Load the documents...
XmlElement xmlInner = (XmlElement)document1.SelectSingleNode("/document1/inner");
xmlInner.AppendChild(document1.ImportNode(document2.DocumentElement, true));
You can, but effectively a copy will be created. You have to use XmlNode node = document1.ImportNode(document2.RootElement), find the node and add node as a child element.
Example on msdn: http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.importnode.aspx
No. You can only have on XmlDocument in an XML DOM. What you want to do is get the DocumentElement associated with document2 and append that XmlElement as a child to the XmlElement.