views:

108

answers:

2

Hello,

I'm trying to find the first attribute in an xml file that contains the string "name" (case insensitve) in it and then change its value.

Here is an example of my xmls

//XML 1
<CtApproachTypes  
 DataclassId="1992A9CE-B048-4676-BFD4-FD81F1A65401"  
 EntityId="1992A9CE-B048-4676-BFD4-FD81F1A65401"  
 Name="PAR"  
 Remark="No Remarks"></CT_ApproachTypes> 

//XML 2
<MiMissions  
 DataclassId="C196A66B-4FA1-461C-9EEF-95A4F2085051"  
 EntityId="C196A66B-4FA1-461C-9EEF-95A4F2085051"  
 MissionName="Standard" 
 Visib="1"></MiMissions> 

//XML 3
<StSituations  
 DataclassId="679FAC3C-C9EF-41FD-9A13-957915605F01"  
 EntityId="679FAC3C-C9EF-41FD-9A13-957915605F01"  
 Sname="Standard"  
 Status="C"  
 Template="1"></StSituations> 

I wanna be able to modify the values of "Name", "MissionName", "Sname", and print them out to console

EDIT here is my code

        public void updateXmlFile(string strFileName)
    {
        try
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(strFileName);

            string newValue = GetUniqueKey();

            XmlNodeList list = doc.SelectNodes("@*"); 
            IEnumerable<XmlNode> filteredList= list.Cast<XmlNode>().Where(item=>item.Value.ToLower().Contains("name"));

            foreach (XmlNode n in filteredList)
            {
                Console.WriteLine("NODES ARE : {0}", n);
            }
                doc.Save(strFileName);

        }
        catch (XmlException xex) { Console.WriteLine(xex); }

    }

This didn't print out anything and I need still to modify the original value with the string newValue

+1  A: 

What you could do, is first select all XML attributes, then use LINQ to select all attributes containing 'Name'.

XmlDocument document = new XmlDocument();
...
XmlNodeList list = document.SelectNodes("@*");
IEnumerable<XmlNode> filteredList= list.Cast<XmlNode>().Where(item=>item.Value.ToLower().Contains("name"));

I hope this points you in the right direction.

Edit:

Reda, you were absolutely right, I made some mistakes. This code worked on my machine ;-) I added comments where I altered your code.

    public void updateXmlFile(string strFileName)
    {
        try
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(strFileName);

            string newValue = GetUniqueKey();

            XmlNodeList list = doc.SelectNodes("//@*"); // Forgot the slashes here...
            IEnumerable<XmlNode> filteredList = list.Cast<XmlNode>().
                Where(item => item.Name.ToLower().Contains("name")); // Name property instead of Value

            foreach (XmlNode n in filteredList)
            {
                n.Value = newValue; // Setting the value.
                Console.WriteLine("FILTERED NODES ARE : {0}", n.Value);
            }

            doc.Save(strFileName);

        }
        catch (XmlException xex) { Console.WriteLine(xex); }

    }
Jeroen
@Jeroen: Check my Edited Post!
Reda
@Jeroen: I tried to print out the 'n' alone, the output was System.Xml.XmlAttribute! In my first post the example shows 3 seperate XMLs and not Nodes of the same XML, I guess thatÄs why I'm getting such output
Reda
Is that something you didn't expect? The nodes are of type 'System.Xml.XmlAttribute', so that is what gets printed.
Jeroen
then why are the attributes in the XMLs not changed?
Reda
Oh! I feel so stupid now. I was checking the old XMLs :S The code works thanks a lot Jeroen. Can I only change the first attribute that cotains the string name?
Reda
Yes, replace the Where method call with a First method call: XmlNode firstNode = list.Cast<XmlNode>(). First(item => item.Name.ToLower().Contains("name"));
Jeroen
Thanks again I really appreciate the quick answer
Reda
+1  A: 

I would use the XDocument object, because it is easy to query with linq. It's in the System.Xml.Linq namespace and assembly.

public void updateXmlFile(string strFileName)
{
    XDocument xDoc = XDocument.Load(strFileName);

    var nameAttributes = from el in xDoc.Root.Elements()
                         from attr in el.Attributes()
                         where attr.Name.ToString().ToLower().Contains("name")
                         select attr;

    foreach (var attribute in nameAttributes)
    {
        attribute.Value = "newValue";
        Console.WriteLine("{0}: {1}", attribute.Name, attribute.Value);
    }

    xDoc.Save(strFileName);
}

Update

This is the output, given the XML in your example if it is saved into a single file:

Name: newValue
MissionName: newValue
Sname: newValue
Matt Ellen
Thanks Matt that's also a good way to query (I was actually trying to solve it using XDocument)
Reda