I have an xml file. It contains records as in the example below.
<Simulator>
<Flight ID="1" Description="1sunny" Date="2022-09-09">
<Instructor Num="6">
<Name>matt</Name>
<Surname>matt</Surname>
<Rank>matt</Rank>
</Instructor>
</Flight>
</Simulator>
When I delete it with the delete function, I see such a result and this result breaks my auto generate id function. How can I get the flight tag to be deleted completely?
<Simulator>
<Flight />
</Simulator>
Delete function
private void b_delete_Click(object sender, EventArgs e)
{
var xDoc = XDocument.Load(input);
foreach (var elem in xDoc.Document.Descendants("Flight"))
{
foreach (var attr in elem.Attributes("ID"))
{
if (attr.Value.Equals("1"))
elem.RemoveAll();
}
}
xDoc.Save(input);
MessageBox.Show("Deleted Successfully");
}
CodePudding user response:
Instead of using a loop, you can get the right element with the LINQ Where
extension method. This is the reason why the XDocument
stuff is in the System.Xml.Linq Namespace
(I am using C# 11's raw string feature for this test):
string xml = """
<Simulator>
<Flight ID="1" Description="1sunny" Date="2022-09-09">
<Instructor Num="6">
<Name>matt</Name>
<Surname>matt</Surname>
<Rank>matt</Rank>
</Instructor>
</Flight>
</Simulator>
""";
var xDoc = XDocument.Parse(xml);
xDoc.Root?.Descendants("Flight")
.Where(f => f.Attribute("ID")?.Value == "1")
.Remove();
Console.WriteLine(xDoc);
Prints:
<Simulator />
IntelliSense told me that Root
and Attribute("ID")
can be null. Therefore I used the C# Null-Conditional Operator (? Operator).
If you want to remove only one element, you can speed up the process by using FirstOrDefault
instead of Where
:
xDoc.Root?.Descendants("Flight")
.FirstOrDefault(f => f.Attribute("ID")?.Value == "1")
?.Remove();
This will stop looping at the first element found. This requires another ?
as FirstOrDefault
will return null
if no matching element was found, whereas Where
returns an empty enumeration.
Note that with Where
we are using
public static void Remove<T>(this IEnumerable<T?> source) where T : XNode;
with T
as XElement
, but with FirstOrDefault
we call the XNode.Remove();
method.
CodePudding user response:
Just use Remove
extension methodon result of Descendants
method:
using System.Xml.Linq;
var xDoc = XDocument.Load(input);
xDoc.Document.Descendants("Flight")
.Remove();
using var writer = new FileStream(output, FileMode.Append);
xDoc.Save(writer);