tags:

views:

106

answers:

2

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.

+2  A: 

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;
}   
marc_s
Also you can call just `SelectNodes("//slide")`, if I'm not wrong
abatishchev
@marc_s Hey, your explanation about xlmdoc.DocumentElement and code example are great. I changed it very slightly to get to work properly: XmlNode node = nodelist.Item(selectedIndex); if (node.Attributes["title"] != null) { titleTextBox.Text = node.Attributes["title"].InnerText; }Thank you Marc.
Doug
@abatishchev: yes you can - but it's not very good for performance and it will search for a "slide" entry anywhere in the document. That may or may not be what you're looking for....
marc_s
So it's better to use the most exact path as you can, right?
abatishchev
@abatishchev: yes, the more specific you can be - especially avoiding any // in your XPath - the better your performance will be.
marc_s
I will take it into account, thanks!
abatishchev
A: 

@title is a XPath call for attributes, i.e. "//slide['@title']"

XmlNode.Attributes holds attributes just by name - title, i.e. node.Attributes["title"]

abatishchev