update and save xml node - c#

hello I have this xml code
<AriaGostarInformation>
<MenuInformation>
<MenuNames Name="1">
home
</MenuNames>
<MenuNames Name="2">
pages
</MenuNames>
<MenuNames Name="3">
blog
</MenuNames>
<MenuNames Name="4">
gallery
</MenuNames>
<MenuNames Name="5">
about us
</MenuNames>
<MenuNames Name="6">
contact us
</MenuNames>
<SubMenuNames parentName="1">
fgfgfgfgs
</SubMenuNames>
<SubMenuNames parentName="3">
</SubMenuNames>
</MenuInformation>
</AriaGostarInformation>
and c# code:
public void updateXmlNodeWithAttribute(string XmlNodeName, string XmlAttributeName, List<string> XmlNodeAttribute, List<string> XmlNodeValue)
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(_connection);
XmlNodeList xnode = getXmlNodeList(XmlNodeName);
for (int i = 0; i < XmlNodeAttribute.Count - 1; i++)
{
foreach (XmlNode item in xnode)
{
if (item.Attributes[XmlAttributeName].Value == XmlNodeAttribute[i].ToString())
{
item.InnerText = XmlNodeValue[i].ToString();
}
}
}
xdoc.Save(_connection);
}
The getXmlNodeList method return Specified xmlnodelist from XML file
This code does not throw an error, but DOES NOT update the XML node.
public XmlNodeList getXmlNodeList(string XmlNodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(_connection);
XmlNodeList elemList = doc.GetElementsByTagName(XmlNodeName);
return elemList;
}
Please help me where is error in my code?

I found two problems in your code.
The first error is in your for loop. With -1 the last element in the List is always not used. Or if you only have one element in your list the for loop is never executed.
The second problem is, that you load the XML file twice. First time you load it in the updateXmlNodeWithAttribute method. Second time you load it in the getXmlNodeList method.
You must know that each loaded XML Document is independent from other loaded XML Document.
So what your code does is you get a List with XML Nodes from your XML file loaded in the getXmlNodeList Method, edit one of these XML Nodes and then you try to save the XML Document loaded in the updateXmlNodeWithAttribute method where no changes were made because the two XML Documents are completely independent.
So what you have to do is use the same XmlDocument object in both methods.
See the code below.
public static void updateXmlNodeWithAttribute(string XmlNodeName, string XmlAttributeName, List<string> XmlNodeAttribute, List<string> XmlNodeValue)
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(_connection);
XmlNodeList xnode = getXmlNodeList(XmlNodeName,xdoc);
for (int i = 0; i < XmlNodeAttribute.Count; i++)
{
foreach (XmlNode item in xnode)
{
if (item.Attributes[XmlAttributeName].Value == XmlNodeAttribute[i].ToString())
{
item.InnerText = XmlNodeValue[i].ToString();
}
}
}
xdoc.Save(_connection);
}
public static XmlNodeList getXmlNodeList(string XmlNodeName, XmlDocument doc)
{
XmlNodeList elemList = doc.GetElementsByTagName(XmlNodeName);
return elemList;
}

Related

ExceptionLogger with using xml

I am writing to ask you about such question. So i have method which writes exception's info into xml file, but if some exception processed, this method replace all that it is in that file. I want that method write to end file a new info about exception
Code of my method is given below:
public void WriteIntoFile()
{
XDocument xdoc = new XDocument(
new XElement("Exceptions",
new XElement("Exception",
new XElement("Message",this.ErrorMessage.ToString())
)));
xdoc.Save("1.xml");
}
Please, help me with it
This should do the Job, assuming the file exists and you create a new node call "Exceptions".
public void WriteIntoFile(string Message)
{
const string Path = "C:\\Temp\\Log.xml";
XmlDocument MyDocument = new XmlDocument();
MyDocument.Load(Path);
XmlNode ExceptionsNode = MyDocument.CreateElement("Exceptions");
XmlNode ExceptionNode = MyDocument.CreateElement("Exception");
XmlNode MessageNode = MyDocument.CreateElement("Message");
MessageNode.InnerText = Message;
ExceptionNode.AppendChild(MessageNode);
ExceptionsNode.AppendChild(ExceptionNode);
MyDocument.AppendChild(ExceptionsNode);
}
if you want the "Exception"- Node append to a existing "Exceptions" node, use this:
XmlNode ExceptionsNode = MyDocument.SelectSingleNode("/Exceptions");
Greetings from Austria.

How to display a large XML file (>21MB) in a tree view quickly

I need to display a large XML file (>21MB) in a tree view control in a C# Windows Form application. I have written the code which is working for small XML files but when i am trying to open a BIG XML file (>1 MB), its taking too much of time.
Can anyone suggest how i can optimise this and suggest me any changes or alternatives to achieve this.
Below is the code snippet:
private void CreateTreeViewFromATXML(string strSrcFileName)
{
XmlDataDocument xmldoc = new XmlDataDocument();
XmlNode xmlnode ;
FileStream fs = new FileStream(strSrcFileName, FileMode.Open, FileAccess.Read);
xmldoc.Load(fs);
xmlnode = xmldoc.ChildNodes[1];
XMLTreeView.Nodes.Clear();
XMLTreeView.Nodes.Add(new TreeNode(xmldoc.DocumentElement.Name));
TreeNode tNode ;
tNode = XMLTreeView.Nodes[0];
AddNode(xmlnode, tNode);
}
private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
//XmlNode xNode ;
TreeNode tNode ;
XmlNodeList nodeList ;
int i = 0;
if (inXmlNode.HasChildNodes)
{
nodeList = inXmlNode.ChildNodes;
foreach (XmlNode XNode in inXmlNode.ChildNodes)
{
tNode = new TreeNode(XNode.Name);
inTreeNode.Nodes.Add(tNode);
AddNode(XNode, tNode);
}
}
else
{
inTreeNode.Text = inXmlNode.InnerText.ToString();
}
}
I would wrap your code like this:
XMLTreeView.BeginUpdate();
try
{
CreateTreeViewFromATXML(strSrcFileName);
}
catch (Exception e)
{
//Handle any error
}
finally
{
XMLTreeView.EndUpdate();
}
If you're not in an update block it's repainting the GUI on every node add and that's expensive. You also have recursion in AddNode but if the XML isn't too deeply nested it shouldn't be an issue.
I would suggest using XDocument and XML to Linq for a faster parsing. You can use the following code to parse the XML:
using System.Xml;
using System.Xml.Linq;
using System.Data;
XDocument xdoc = XDocument.Load(XMLFile);
var item = from items in xdoc.Element("EPICORTLOG").Descendants("POS")
where (string)items.Element("Id") == strSelectedPOSID
select items.Elements("TRADE").Elements("ITEM").ToList().ToList();
You can then follow the explanation in the following link to parse the XML:
http://www.dotnetcurry.com/showarticle.aspx?ID=564
The article above will explain the XML to LINQ programming. Using the above method you can load XML files as big as 10MB in a short time.
Recently, I used TreeView component to implement my HTML editor in C#, I used serialized data structure to impove the performance to open and save a XML file.
From my experience , using this structure and serialize read and write file can open file up to 20M byes within 2 seconds in my computer. This solution can open a XML file over 2G bytes in my C# application. Hope this solution can help you better.
Example to define Serializable Structure for TreeView and TreeNode
[Serializable]
public class TreeViewData
{
public TreeNodeData[] Nodes;
public TreeViewData(){ }
public TreeViewData(TreeView treeview)
{
//your code
}
public TreeViewData(TreeNode treenode)
{
//your code
}
public void PopulateTree(TreeView treeview)
{
//your code
}
public void PopulateSubTree(TreeNode treenode)
{
//your code
}
}
[Serializable]
public class TreeNodeData
{
public string Text;
public int ImageIndex;
public int SelectedImageIndex;
public string Tag;
public TreeNodeData[] Nodes;
public TreeNodeData() {}
public TreeNodeData(TreeNode node)
{
// your code
}
public TreeNode ToTreeNode()
{
// your code
}
}
Example to serialize read XML file
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(TreeViewData));
System.IO.FileStream file = new System.IO.FileStream(strFilename, FileMode.Open);
System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(file);
TreeViewData treeData = (TreeViewData)ser.Deserialize(reader);
treeData.PopulateTree(TreeView1);
Example to serialize write XML file
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(TreeViewData));
System.IO.FileStream file = new System.IO.FileStream(strFilename, System.IO.FileMode.Create);
System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(file, null);
ser.Serialize(writer, new TreeViewData(TreeView1));

Method is executed but not has effect

I'm creating a class for manipulate XML, I created overload of my method RemoveNode
public partial class HWXml
{
public string XmlFile;
private XmlDocument XmlDoc = new XmlDocument();
public HWXml(string XmlFile)
{
this.XmlFile = XmlFile;
}
public XmlNode SelectSingleNode(string NodePath)
{
XmlDoc.Load(XmlFile);
return XmlDoc.SelectSingleNode(NodePath);
}
public void RemoveNode(XmlNode removeChild)
{
XmlDoc.Load(XmlFile);
removeChild.ParentNode.RemoveChild(removeChild);
XmlDoc.Save(XmlFile);
}
public void RemoveNode(string RemoveChild)
{
XmlDoc.Load(XmlFile);
XmlNode removeChild = XmlDoc.SelectSingleNode(RemoveChild);
removeChild.ParentNode.RemoveChild(removeChild);
XmlDoc.Save(XmlFile);
}
}
When I try remove node using string parameter, it works
private void RemoveXML_Click(object sender, RoutedEventArgs e)
{
MyXmlClass myXmlClass = new MyXmlClass(XmlFile);
myXmlClass.RemoveNode("root/Content");
}
But when I try remove node using XmlNode parameters, it will compile, execute, no error message, but no effect, it no remove nothing in the XML file.
private void RemoveXML_Click(object sender, RoutedEventArgs e)
{
MyXmlClass myXmlClass = new MyXmlClass(XmlFile);
XmlNode node = myXmlClass.SelectSingleNode("root/Conteudo");
myXmlClass.RemoveNode(node);
}
What is problem?
XmlNode parameter is definitely not part of XmlDoc which you are loading inside this method (because you have this node before document is loaded). Thus manipulations on this node do not affect document which node does not belong to.
In second case you are selecting node of document which was loaded. This node belongs to xml tree which was just loaded into XmlDoc, thus removing node affects document.
What you should understand is how XmlDocument (same for XDocument) is loaded:
If it has some nodes (previously loaded) then all nodes are removed
XmlReader created
This reader reads input stream node by node
For each found node, new instance of appropriate class is created and added to document (e.g. if reader has read some element, then new XmlElement is created and added to current element of document)
So, you end up with graph of completely new objects which have no relation to objects which was created during previous load of xml. After loading xml, instance of XmlDocument stays same, but it has completely new objects inside.

How to append ChildNodes of a xml documents into root of another (web services)?

I've created a [WebMethod] on ASP.NET Web Service which reads XML documents from different web services (ASP.NET and PHP services).
Once the documents are read, they are merged into a XML and returned.
The method can successfully read XML documents from each web service but when I try to append second XML into first one, I get ArgumentException and a message like this The node to be inserted is from a different document context. I can't find a problem, can it be something to do with the source of document? but then both document are exactly same (have same elements).
Why ArgumentException? What am I missing?
[WebMethod]
public XmlDocument getRestaurants(String search_keywords)
{
XmlDocument xmlDom1 = new XmlDocument();
xmlDom1 = getRestaurantFromAspNetWS(search_keywords);
XmlTextReader myXmlTextReader =
new XmlTextReader
("http://some-iss.green.com/username/search.php?s=" + search_keywords);
XmlDocument xmlDom2 = new XmlDocument();
xmlDom2.Load(myXmlTextReader);
foreach (XmlElement xmlNode in xmlDom2.DocumentElement.ChildNodes)
{
//trying to append childNodes of xmlDom2 into xmlDom1
//and this is where i get ArgumentException
xmlDom1.DocumentElement.AppendChild(xmlNode);
}
return xmlDom1;
}
You need to import the node with importNode()
something like this:
xmlDom1.DocumentElement.importNode(xmlNode, true);
Can you write it like this?
public XElement getRestaurants(String search_keywords)
{
XElement result = getRestaurantFromAspNetWS(search_keywords);
XmlTextReader myXmlTextReader = new XmlTextReader
("http://some-iss.green.com/username/search.php?s=" + search_keywords);
XElement reader = XElement.Load(myXmlTextReader);
foreach (XElement child in reader.Elements())
result.Add(child);
return result;
}
The real trick is getting your custom getRestaurantFromAspNetWS function to return a XElement instead of a XmlDocument, as you didn't provide us with that function, I can't help you there.

How Can I Retrieve All XmlEntityReference Objects In An XmlDocument Object?

I have a number of xml documents from which I want to retrieve all of the entity references and perform some updates on the documents. I am using an XmlDocument object to do the updates. What is the best way to retrieve all entity references from an XmlDocument object?
This may not be the best or most efficient solution, but in light of the fact that I did not receive any other answers, this is what I came up with:
XmlTextReader reader = new XmlTextReader(stream);
reader.EntityHandling = EntityHandling.ExpandCharEntities;
XmlDocument doc = new XmlDocument();
doc.Load(reader);
List<XmlEntityReference> entityRefs = new List<XmlEntityReference>();
RetrieveEntityRefs(doc.DocumentElement, doc, entityRefs);
private void RetrieveEntityRefs(XmlNode parentNode, XmlDocument doc, List<XmlEntityReference> entityReferences) {
foreach (XmlNode node in parentNode.ChildNodes)
{
if (node.NodeType == XmlNodeType.EntityReference) {
XmlEntityReference entityRef = node as XmlEntityReference;
entityReferences.Add(entityRef);
}
else if (node.HasChildNodes) {
RetrieveEntityRefs(node, doc, entityReferences);
}
}
}

Categories