tags:

views:

242

answers:

3

I'm writing one of my first C# programs. Here's what I'm trying to do:

  • Open an XML document
  • Navigate to a part of the XML tree and select all child elements of type <myType>
  • For each <myType> element, change an attribute (so <myType id="oldValue"> would become <myType id="newValue">
  • Write this modified XML document to a file.

I found the XmlDocument.SelectNodes method, which takes an XPath expression as its argument. However, it returns an XmlNodeList. I read a little bit about the difference between an XML node and an XML element, and this seems to explain why there is no XmlNode.SetAttribute method. But is there a way I can use my XPath expression to retrieve a list of XmlElement objects, so that I can loop through this list and set the id attributes for each?

(If there's some other easier way, please do let me know.)

+1  A: 

Simply - it doesn't know if you are reading an element or attribute. Quite possibly, all you need is a cast here:

foreach(XmlElement el in doc.SelectNodes(...)) {
    el.SetAttribute(...);
}

The SelectNodes returns an XmlNodeList, but the above treats each as an XmlElement.

Marc Gravell
This works just fine. And it's generally safe to do, since if you want to write an XPath query that returns more than one node type you have to work at it.
Robert Rossney
@Robert - well, it could be an attribute or text node; the xpath would be pretty similar... but in this case the OP states they are reading elements; *that* is what makes it safe.
Marc Gravell
A: 

I'm sitting at my Mac so no .NET for me...

However, I think that you can cast an XmlNode to an XmlElement via an explicit cast.

You should be able to cast the XmlElement to an XmlNode then and get it's children Nodes using something like XmlNode.ChildNodes.

Andrew Flanagan
+1  A: 

I am a big fan of System.Xml.Linq.XDocument and the features it provides.

XDocument xDoc = XDocument.Load("FILENAME.xml");

// assuming you types is the parent and mytype is a bunch of nodes underneath
IEnumerable<XElement> elements = xdoc.Element("types").Elements("myType");

foreach (XElement type in elements)
{
    // option 1
    type.Attribute("id").Value = NEWVALUE;
    // option 2
    type.SetAttributeValue("id", NEWVALUE);
}

Option 1 or 2 works but I prefer 2 because if the attribute doesn't exist this'll create it.

ahsteele
Thanks; I'll check this out. Looks very handy.
RexE