I have Data.xml:
<?xml version="1.0" encoding="utf-8" ?>
<data>
<album>
<slide title="Autum Leaves"
description="Leaves from the fall of 1986"
source="images/Autumn Leaves.jpg"
thumbnail="images/Autumn Leaves_thumb.jpg" />
<slide title="Creek"
description="Creek in Alaska"
source="images/Creek.jpg"
thumbnail="images/Creek_thumb.jpg" />
</album>
</data>
I'd like to be able to edit the attributes of each Slide node via GridView (that has a "Select" column added.) And so far I have:
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
int selectedIndex = GridView1.SelectedIndex;
LoadXmlData(selectedIndex);
}
private void LoadXmlData(int selectedIndex)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(MapPath(#"..\photo_gallery\Data.xml"));
XmlNodeList nodelist = xmldoc.DocumentElement.ChildNodes;
XmlNode xmlnode = nodelist.Item(selectedIndex);
titleTextBox.Text = xmlnode.Attributes["title"].InnerText;
descriptionTextBox.Text = xmlnode.Attributes["description"].InnerText;
sourceTextBox.Text = xmlnode.Attributes["source"].InnerText;
thumbTextBox.Text = xmlnode.Attributes["thumbnail"].InnerText;
}
The code for LoadXmlData is just a guess on my part - I'm new to working with xml in this way. I'd like have the user to slected the row from the gridview, then populate a set of text boxes with each slide attributed for updating back to the Data.xml file.
The error I'm getting is Object reference not set to an instance of an object" at the line: titleTextBox.Text = xmlnode.Attributes["#title"].InnerText;
so I'm not reaching the attribute "title" of the slide node. Thanks for any ideas you may have.
Well yes - given your XML, the xmldoc.DocumentElement.ChildNodes; statement will give you exactly one node - the <album> node - and it doesn't have any attribute called ["title"].
You need to
change the way you select your nodes; the xmldoc.DocumentElement corresponds to the <data> node, and it's .ChildNodes collection will include all the direct child nodes - which in this case is the one and only <album> node - nothing else.
check for existence! (and not just assume it works...)
Try this:
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(MapPath(#"..\photo_gallery\Data.xml"));
XmlNodeList nodelist = xmldoc.SelectNodes("/data/album/slide");
foreach(XmlNode xmlnode in nodelist)
{
if(xmlnode.Attributes["title"] != null
titleTextBox.Text = xmlnode.Attributes["title"].InnerText;
if(xmlnode.Attributes["description"] != null
descriptionTextBox.Text = xmlnode.Attributes["description"].InnerText;
if(xmlnode.Attributes["source"] != null
sourceTextBox.Text = xmlnode.Attributes["source"].InnerText;
if(xmlnode.Attributes["thumbnail"] != null
thumbTextBox.Text = xmlnode.Attributes["thumbnail"].InnerText;
}
#title is a XPath call for attributes, i.e. "//slide['#title']"
XmlNode.Attributes holds attributes just by name - title, i.e. node.Attributes["title"]
Related
I am trying to update my grid in edit mode using xml but I am not able to do it.
I am able to edit only one element but dont know how to edit more than one
my xml file looks like below
<CATALOG>
<CD>
<ID>1</ID>
<Application>Dot Net</Application>
<status>Available</status>
<LastUpdate>02-07-2017</LastUpdate>
<Comments>The Rox for July has been loaded</Comments>
</CD>
<CD>
<ID>2</ID>
<Application>JFORWBK</Application>
<status>Available</status>
<LastUpdate>05-07-2017</LastUpdate>
<Comments>DeLorean data has been loaded</Comments>
</CD>
<CD>
<ID>3</ID>
<Application>Codepress</Application>
<status>Open for Input</status>
<LastUpdate>06-07-2017</LastUpdate>
<Comments>The Rox for July has been loaded</Comments>
</CD>
</catalog>
When i open the data in grid in edit mode basis of id than I am able to update on single element
How can i update all the element in one time if i have the value in hidden field.
I am able to update my xml element on basis of id.I am only able to update one element in 1 time..
Code as follows:
ID = Request.QueryString["sID"];
XmlDocument xmlDoc = new XmlDocument();
string filepathsUpdate = Server.MapPath("Action.xml");
xmlDoc.Load(filepathsUpdate);
XmlNode node = xmlDoc.SelectSingleNode("/CATALOG/CD[ID=" + ID + "]/Action");
node.InnerText = ssplit[0];
xmlDoc.Save(filepathsUpdate);
Now How do it update ,, and comments in edit mode on click of update button in C# on server side.
Why don't you use a loop to update them one by one like.
Put you all hidden field values in Ids list. Then use a loop to update the XML.
List<int> Ids = new List<int>();
Ids.Add(1);
for (int i = 0; i < Ids.Count; i++)
{
ID = Request.QueryString["sID"];
XmlDocument xmlDoc = new XmlDocument();
string filepathsUpdate = Server.MapPath("Action.xml");
xmlDoc.Load(filepathsUpdate);
XmlNode node = xmlDoc.SelectSingleNode("/CATALOG/CD[ID=" + Ids[i].ToString() + "]/Action");
node.InnerText = ssplit[0];
xmlDoc.Save(filepathsUpdate);
}
In LINQ to XML it is pretty straightforward:
var id = Request.QueryString["sID"];
XDocument doc = XDocument.Load("Action.xml");
var catalogDescendants = doc.Descendants("CATALOG");
foreach (var cd in catalogDescendants)
{
//you can update the id here for whatever you want
cd.Element("ID").Value = id;
}
You could use the XmlNodeList and iterate for each XmlNode within that list and perform an update.
If memory serves it ought to be along the lines of
foreach(XmlNode node in XmlDoc.selectNodes("nodename")){node.innerText = "updated value here";}
Using C# I have an XML file like
<?xml version="1.0" encoding="utf-8"?>
<root>
<Account>
<name>Jani</name>
</Account>
</root>
and I also have a function to read the name node as:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("lib//user.xml");
XmlNode node;
node = xmlDoc.DocumentElement;
string name = node.Attributes[0].Value;
label1.Text = name.ToString();
but I am getting index out of range error as:
Why is this happening?
node = xmlDoc.DocumentElement;
string name = node.Attributes[0].Value;
node is your root node. Which looks like this:
<root>
How many attributes does it have? None, as it turns out. An attribute in XML is one of these bar="baz" things:
<foo bar="baz">
node.Attributes[0] refers to the first attribute. There is no first attribute, there's no second attribute -- you didn't use attributes in this XML at all. Hence, that's out of range. There's no first item in an empty collection.
What you want is an element named name, which is farther down inside your XML tree.
Probably this:
var node = xmlDoc.DocumentElement.SelectSingleNode("/root/Account/name");
And then you'll want to look at node.InnerText to get "Jani" out of it.
You are trying to read node.Attributes[0].Value but there is no attribtues in your sample XML file. Not sure of the exact syntax but it should probably be closer to node.Value
As mentioned by other answers, your current XML does not have attributes.
private void DoIt()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"M:\StackOverflowQuestionsAndAnswers\38924171\38924171\data.xml");
XmlNode node;
node = xmlDoc.DocumentElement;
//string name = node.Attributes[0].Value;
string name = node["Account"].InnerText;
}
If your XML did have attributes
<?xml version="1.0" encoding="utf-8"?>
<root>
<Account name="Jani" />
</root>
Then you could do this:
private void DoItAgain()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"M:\StackOverflowQuestionsAndAnswers\38924171\38924171\data2.xml");
XmlNode node;
node = xmlDoc.DocumentElement;
string name = node["Account"].Attributes[0].Value;
}
I have the following code, which I use to traverse the XML:
private void btn_readXML_Click(object sender, EventArgs e)
{
var doc = new XmlDocument();
doc.Load("e:\\contacts.xml");
// Load xml document.
TraverseNodes(doc.ChildNodes);
}
static List<string> xmlnodes = new List<string>();
private static void TraverseNodes(XmlNodeList nodes)
{
foreach (XmlNode node in nodes)
{
List<string> temp = new List<string>();
temp.Add("Node name: " + node.Name.ToString());
XmlAttributeCollection xmlAttributes = node.Attributes;
foreach (XmlAttribute at in xmlAttributes)
{
temp.Add(" Atrib: " + at.Name + ": " + at.Value);
}
xmlnodes.AddRange(temp);
TraverseNodes(node.ChildNodes);
}
But my problem is, I don't want to traverse the whole document, I only want to traverse the node and subsequently its children which has an attribute 'X'. Please note that I don't know where the node is present. So basically what I have to do is, find out if the node exists ( it'll have the attribute 'X'. That's how I identify its the right node) if yes then fetch its children.
Can anyone help me out here? I'm pretty new to XMLs. Thanks is advance!
Assuming your XML having following structure:
<Contacts>
<Contact X="abc">
<Child1></Child1>
</Contact>
<Contact X="def">
<Child2></Child2>
</Contact>
</Contacts>
Example code using XmlNode.SelectNodes:
var doc = new XmlDocument();
doc.Load("e:\\contacts.xml");
//get root element of document
XmlElement root = doc.DocumentElement;
//select all contact element having attribute X
XmlNodeList nodeList = root.SelectNodes("//Contact[#X]");
//loop through the nodelist
foreach (XmlNode xNode in nodeList)
{
//traverse all childs of the node
}
For different XPath Queries see this link.
UPDATE:
If you want to select all elements having attribute X in the document. No matters where they exists. You could use following:
//select all elements in the doucment having attribute X
XmlNodeList nodeList = root.SelectNodes("//*[#X]");
Try this:
private void btn_readXML_Click(object sender, EventArgs e)
{
var doc = new XmlDocument();
doc.Load("e:\\contacts.xml");
var nodes = xdoc.SelectNodes("//yournodename");
// ex.
// var nodes = xdoc.SelectNodes("//Company");
TraverseNodes(nodes);
}
this is simple code for using xml in C#. I want to add data like
<table1 name="something">
<column1 someattribute="something"> actualname </column>
</table1>
then I want to add this element into XDocument's Object
XDocument document;
public Form1()
{
InitializeComponent();
document = new XDocument();
}
private void button1_Click(object sender, EventArgs e)
{
//document = new XDocument();
XElement elem = new XElement("table1");
elem.Add(new XAttribute("TableName", textBox1.Text));
elem.Add(new XElement("Column1",new XAttribute("Someattribute", somevalue));
document.Element("table1").Add(elem);//throws exception object refernce not set ..."
}
I have tried the following code Adding elements to an xml file in C# but it throws an exception of "object reference not set to an instance of an object xml C#"
Please help
P.S: suppose there are many columns in table1 then first I want to accmulate each column then add it to xdocument and then there is table2 and I want to do the same thing with him.
There are no table1 elements in your XML structure. This means that your document.Element("table1") table returns null, and therefore there is an exception when you call .Add(elem) on it.
Debugging NullReferenceExceptions is very basic most of the time and these problems can easily be solved simply by stepping through the code with a debugger.
For reference, the Element method
Gets the first (in document order) child element with the specified XName.
Which is why you get a null. (MSDN)
When you initialize the form, you create an empty document like so new XDocument(). Then, in your button click, you are trying to add a new element as a child to table1 by using the selector document.Element("table1"). That is the issue, your XDocument is empty! You would need to first create a table1 element or instead add your elem object directly to the document.
Meaning you can either do this to make sure table1 exists:
document = XDocument.Parse("<table1></table1>);
or change your click method to add directory to the root of the document:
private void button1_Click(object sender, EventArgs e)
{
//document = new XDocument();
XElement elem = new XElement("table1");
elem.Add(new XAttribute("TableName", textBox1.Text));
elem.Add(new XElement("Column1",new XAttribute("Someattribute", somevalue)));
document.Add(elem);
}
Every XML document/structure has to have one unique node/tag, called the root node, that should exist only once in every document. So a proper xml can look like this - one root, but many nodes:
<?xml version="1.0" encoding="UTF-8"?>
<root name="example">
<node attribute="1">information 1</node>
<node attribute="2">information 2</node>
</root>
There are two possibilities to access the root element using LINQ2XML: XDocument.Root and XDocument.Element("elementName").
Knowing this and using the given xml code, it should be easy to follow the following example, that uses LINQ2XML to manipulate the xml code:
// every XML structure has to have a root node, that is unique
// and should exists only once!
var xmlCode = #"<root name=""example"">
<node attribute=""1"">information 1</node>
<node attribute=""2"">information 2</node>
</root>";
// load the example xml code
var document = XDocument.Parse(xmlCode);
// create new attribute object
var newAttribute = new XAttribute("attribute", "3");
// create new node / column object with the newly created attribute and set the content of the node
var newNode = new XElement("node", newAttribute, "information 3");
// add the newly created node to the XML Document root
// in LINQ2XML the root node can be accessed via the Root property
// of an XDocument object
document.Root.Add(newNode);
// alternative: find the document root node using its name, in this example the node
// is named "root" and add the new element to it!
// document.Element("root").Add(newNode);
The output is:
<root name="example">
<node attribute="1">information 1</node>
<node attribute="2">information 2</node>
<node attribute="3">information 3</node>
</root>
In your question table1 is root in this xml code and column1 equivalent is node.
If you are going to use LINQ2XML, than have a look at all methods that the framework offers.
Throw exception, because at the time the item is inserted in the XDocument(document) XElement (elem) element Element("Table") does not exist yet
You are trying to add your now element to an existing element that doesn't exist:
document.Element("table1").Add(elem);//throws exception object refernce not set ..."
The table1 element hasn't been added to the document yet. You need to reference the appropriate parent element. To add it to the root element use
document.Root.Add(elem);
I want to create a routing(path) to xml element and assign it to a variable so i can access it
fast in the future.
The element, which is a child of other elements, can change its position in the document
so i cant use methods like first child or indexing that rely on position.
The path to the element will always stay constant and there is no other path like it.
If we look at a short example so i want a path to level4 value(header4) so i can modify it.
<level1>
<level2>
<level3>header3</level3>
<level4>header4</level4>
<level3>header31</level31>
</level2>
<level2>
<level3>nnn</level3>
<level3>nnnnn</level31>
</level2>
</level1>
You've got to use XPath in that case.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("Path of the xml");
XmlNode titleNode = xmlDoc.SelectSingleNode("//level1/level2/level3");
You can use XPath for this.
XmlDocument doc; // assuming the xml is already in doc
XmlNode node = doc.SelectSingleNode("/level1/level2/level3/level4");
if(node != null)
{
node.InnerText = "New value";
}
If there could be more than one level4 then you could do this:
XmlDocument doc; // assuming the xml is already in doc
XmlNodeList nodes = doc.SelectNodes("/level1/level2/level3/level4");
if(nodes != null)
{
foreach(XmlNode node in nodes)
{
node.InnerText = "New value";
}
}