0

I am trying to delete one record from the XML based on some attribute value. My XML structure is given below:

<?xml version="1.0" encoding="utf-8"?>
<Users>
  <User>
    <UserId>12345</UserId>
    <FirstName>abcd</FirstName>
    <LastName>efgh</LastName>
    <Email>Hello@hello.com</Email>
    <IsAdmin>No</IsAdmin>
  </User>
  <User>
    <UserId>67890</UserId>
    <FirstName>ijklm</FirstName>
    <LastName>nopqr</LastName>
    <Email>world@world.com</Email>
    <IsAdmin>No</IsAdmin>
  </User>
  <User>
    <UserId>12678</UserId>
    <FirstName>stuv</FirstName>
    <LastName>wxyz</LastName>
    <Email>foo@bar.com</Email>
    <IsAdmin>Yes</IsAdmin>
  </User>
</Users>

E.g if attribute value is 12345 it should delete the below record from the XML.

<User>
        <UserId>12345</UserId>
        <FirstName>abcd</FirstName>
        <LastName>efgh</LastName>
        <Email>Hello@hello.com</Email>
        <IsAdmin>No</IsAdmin>
      </User>

I tried below code but I am not able to delete anything from the XML.

string path = Server.MapPath("~/XML/users.xml");
                XElement xEle = XElement.Load(path);
                var qry = from element in xEle.Descendants()
                          where (string)element.Attribute("UserId").Value == "12345"
                          select element;
                if (qry.Count() > 0)
                    qry.First().Remove();
                xEle.Save(path);

I am unable to figure this out. Any help with be appreciated. Thank you

waris kantroo
  • 83
  • 3
  • 21

2 Answers2

1

<UserId>12345</UserId> is a nested sub-element of <User>, not an attribute. See XML attribute vs XML element to see the difference.

Thus you need to do:

        var userId = "12345";

        var qry = from element in xEle.Descendants("User")
                  where (string)element.Element("UserId") == userId
                  select element;
        var first = qry.FirstOrDefault();
        if (first != null)
            first.Remove();

Incidentally, by calling both Count() and First(), you are evaluating your query twice. FirstOrDefault() returns the first matching element, or null if the enumerable is empty, and is thus more efficient.

dbc
  • 104,963
  • 20
  • 228
  • 340
1

UserId is not attribute in the XML. Its an element

XElement xEle = XElement.Load("input.xml");
        var qry = from element in xEle.Descendants()
                  where (string)element.Element("UserId") == "12345"
                  select element;
        if (qry.Count() > 0)
            qry.First().Remove();
        xEle.Save("input.xml");

And in your snippet you are comparing 12345 int with string type

null1941
  • 972
  • 8
  • 20