emie
emie

Reputation: 289

C# XML Search and Replace

I'm trying to search for a specific XAttribute and XElement.

 <IcMDetails ServerGroup="ABC">
    <IncidentId>984513515</IncidentId>
    <Title>today is a great day</Title>
    <Description>this is a test</Description>
    <State>Active</State>
    <Severity>2</Severity>
    <DateCreated>2016-12-12</DateCreated>
  </IcMDetails>
 <IcMDetails ServerGroup="XYZ">
    <IncidentId>6845613</IncidentId>
    <Title>today is a great day</Title>
    <Description>this is a test</Description>
    <State>Active</State>
    <Severity>2</Severity>
    <DateCreated>2016-12-08</DateCreated>
  </IcMDetails>
 <IcMDetails ServerGroup="ABC">
    <IncidentId>12345345</IncidentId>
    <Title>today is a great day</Title>
    <Description>this is a test</Description>
    <State>Resolved</State>
    <Severity>2</Severity>
    <DateCreated>2016-12-08</DateCreated>
  </IcMDetails>

Where: ServerGroup = ABC State = Active

Once I have found the specific Child record, I want to update the State. I assume I can do something like:

 public static void Update()
   {
     string filePath = "XML.xml"
     XDocument doc = XDocument.Load(filePath);

     var items = from i in doc.Descendants("IcMDetails")
        select i;

      foreach(var item in items)
        {
          item.Element("State").Value = "NewValue";
        }
   }

I used the following to read the XML file. However, I am unable to read the XAttribute value.

    public static void Read()
    {
        XmlTextReader reader = new XmlTextReader("TFS_Tickets.xml");

        while (reader.Read())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element: // The node is an element.
                    Console.Write("<" + reader.Name);
                    Console.WriteLine(">");
                    break;
                case XmlNodeType.Attribute:
                    Console.WriteLine(reader.Value);
                    break;                           
                case XmlNodeType.Text: //Display the text in each element.
                    Console.WriteLine(reader.Value);
                    break;
                case XmlNodeType.EndElement: //Display the end of the element.
                    Console.Write("</" + reader.Name);
                    Console.WriteLine(">");
                    break;
            }
        }

Upvotes: 2

Views: 86

Answers (2)

Charles Mager
Charles Mager

Reputation: 26213

It's fairly simple, you can use LINQ's Enumerable.Where to filter the elements by your criteria, then update them.

var details = doc.Descendants("IcMDetails")
    .Where(x => (string) x.Attribute("ServerGroup") == "ABC" &&
                (string) x.Element("State") == "Active");

foreach (var detail in details)
{
    detail.SetElementValue("State", "NewValue");
}

You can also write the same query in query syntax:

var details =
    from item in doc.Descendants("IcMDetails")
    where (string) item.Attribute("ServerGroup") == "ABC" &&
          (string) item.Element("State") == "Active"
    select item;

See this fiddle for a working demo.

Upvotes: 0

jdweng
jdweng

Reputation: 34421

Using xml linq :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            var results = doc.Descendants("IcMDetails").Where(x => (string)x.Element("State") == "Active").ToList();

        }
    }
}

Upvotes: 1

Related Questions