简体   繁体   中英

remove data from XML file using c#?

I implemented a XML document containing the following data

<TrafficPattern>
    <WayPoint>
        <Radial>001</Radial>
        <Distance>0.36</Distance>
        <Latitude>
            <Degrees>48</Degrees>
            <Minutes>31.7363644</Minutes>
        </Latitude>
        <Longitude>
            <Degrees>11</Degrees>
            <Minutes>57.53425</Minutes>
        </Longitude>
     </WayPoint>
        <WayPoint>
        <Radial>090</Radial>
        <Distance>0.56</Distance>
        <Latitude>
            <Degrees>48</Degrees>
            <Minutes>31.7363644</Minutes>
        </Latitude>
        <Longitude>
            <Degrees>11</Degrees>
            <Minutes>57.53425</Minutes>
        </Longitude>
    </WayPoint>
    <WayPoint>
        <Radial>240</Radial>
        <Distance>0.56</Distance>
        <Latitude>
            <Degrees>48</Degrees>
            <Minutes>31.7363644</Minutes></Latitude>
        <Longitude>
            <Degrees>11</Degrees>
            <Minutes>57.53425</Minutes></Longitude>
    </WayPoint>
    <WayPoint>
        <Radial>346</Radial>
        <Distance>0.56</Distance>
        <Latitude>
            <Degrees>48</Degrees>
            <Minutes>31.7363644</Minutes></Latitude>
        <Longitude>
            <Degrees>11</Degrees>
            <Minutes>57.53425</Minutes></Longitude>
    </WayPoint>
</TrafficPattern>

I wrote the above XML file using XMLDocument .

Now I want to remove a waypoint from the XML file on a button click.

Can any one suggest me a way how I can remove it using XMLDocument ?

I believe you want to use the RemoveChild API. You can also use the SelectSingleNode or SelectNodes APIs to find the nodes you want to remove, move to their parent node and remove them.

You need to use the XmlNode.RemoveChild method, but notice that this will only work if you apply it to the parent of the node you're trying to remove, or you will get the exception:

The node to be removed is not a child of this node

as explained in removing nodes from an XmlDocument .

The following RemoveNode method is based on a simple XML example .

public sealed class TestXmlNodeRemoval
{
    public static void RemoveNode()
    {
        var xmlDocument = new XmlDocument();
        var xmlTrafficPattern = xmlDocument.CreateElement("TrafficPattern");
        xmlDocument.AppendChild(xmlTrafficPattern);

        xmlTrafficPattern.AppendChild(CreateWayPoint(xmlDocument, 
                           "001", "0.36", "48", "31.7363644", "11", "57.53425"));
        xmlTrafficPattern.AppendChild(CreateWayPoint(xmlDocument, 
                           "090", "0.56", "48", "31.7363644", "11", "57.53425"));
        xmlTrafficPattern.AppendChild(CreateWayPoint(xmlDocument, 
                           "240", "0.56", "48", "31.7363644", "11", "57.53425"));
        xmlTrafficPattern.AppendChild(CreateWayPoint(xmlDocument, 
                           "346", "0.56", "48", "31.7363644", "11", "57.53425"));

        Console.WriteLine(@"Original traffic pattern:");
        DisplayXmlDocument(xmlDocument);

        // create an arbitrary criterion to remove an element
        const string radialToRemove = @"090";
        Console.WriteLine(@"Remove node with radial=" + radialToRemove);

        if (xmlDocument.DocumentElement != null)
        {
            for (var i = 0; i < xmlDocument.DocumentElement.ChildNodes.Count; ++i)
            {
                var radial = 
                xmlDocument.DocumentElement.ChildNodes[i].SelectSingleNode("Radial");

                if (radial == null || (radial.InnerText != radialToRemove))
                {
                    continue;
                }

                var nodeToRemove = xmlDocument.DocumentElement.ChildNodes[i];

                // note that you need to remove node from the Parent
                if (nodeToRemove.ParentNode != null)
                {
                    nodeToRemove.ParentNode.RemoveChild(nodeToRemove);
                }

                break;
            }
        }

        Console.WriteLine(@"New traffic pattern:");
        DisplayXmlDocument(xmlDocument);
    }
}

This above method creates the following output:

Original traffic pattern:

Radial:001, Distance:0.36, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

Radial:090, Distance:0.56, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

Radial:240, Distance:0.56, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

Radial:346, Distance:0.56, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

Remove node with radial=090

New traffic pattern:

Radial:001, Distance:0.36, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

Radial:240, Distance:0.56, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

Radial:346, Distance:0.56, Latitude:(48, 31.7363644), Longitude:(11, 57.53425)

The supporting methods I used are copied below.

The first method creates a way point, so the code above isn't so cluttered. For simplicity, everything's a string , but I probably would choose better parameter types

    private static XmlElement CreateWayPoint(XmlDocument xmlDoc, 
                                             string radial, 
                                             string distance,
                                             string latDegrees,
                                             string latMinutes,
                                             string longDegrees,
                                             string longMinutes)
{
    var xmlWayPoint = xmlDoc.CreateElement("WayPoint");

    var xmlRadial = xmlDoc.CreateElement("Radial");
    xmlRadial.InnerText = radial;
    xmlWayPoint.AppendChild(xmlRadial);

    var xmlDistance = xmlDoc.CreateElement("Distance");
    xmlDistance.InnerText = distance;
    xmlWayPoint.AppendChild(xmlDistance);

    var xmlLatitude = xmlDoc.CreateElement("Latitude");
    var xmlLatDegrees = xmlDoc.CreateElement("Degrees");
    xmlLatDegrees.InnerText = latDegrees;
    xmlLatitude.AppendChild(xmlLatDegrees);
    var xmlLatMinutes = xmlDoc.CreateElement("Minutes");
    xmlLatMinutes.InnerText = latMinutes;
    xmlLatitude.AppendChild(xmlLatMinutes);
    xmlWayPoint.AppendChild(xmlLatitude);

    var xmlLongitude = xmlDoc.CreateElement("Longitude");
    var xmlLongDegrees = xmlDoc.CreateElement("Degrees");
    xmlLongDegrees.InnerText = longDegrees;
    xmlLongitude.AppendChild(xmlLongDegrees);
    var xmlLongMinutes = xmlDoc.CreateElement("Minutes");
    xmlLongMinutes.InnerText = longMinutes;
    xmlLongitude.AppendChild(xmlLongMinutes);
    xmlWayPoint.AppendChild(xmlLongitude);

    return xmlWayPoint;
}

And this method displays the XML document:

private static void DisplayXmlDocument(XmlNode xmlDoc)
{
    var wayPoints = xmlDoc.SelectNodes("TrafficPattern/WayPoint");

    if (wayPoints == null)
    {
        return;
    }

    foreach (XmlNode wayPoint in wayPoints)
    {
        var radial = wayPoint.SelectSingleNode("Radial");
        var distance = wayPoint.SelectSingleNode("Distance");
        var latitudeDegrees = wayPoint.SelectSingleNode("Latitude/Degrees");
        var latitudeMinutes = wayPoint.SelectSingleNode("Latitude/Minutes");
        var longitudeDegrees = wayPoint.SelectSingleNode("Longitude/Degrees");
        var longitudeMinutes = wayPoint.SelectSingleNode("Longitude/Minutes");

        if (radial != null && 
            distance != null && 
            latitudeDegrees != null && 
            latitudeMinutes != null && 
            longitudeDegrees != null && 
            longitudeMinutes != null)
        {
            Console.WriteLine(string.Format("Radial:{0}, 
                                            Distance:{1}, 
                                            Latitude:({2}, {3}),
                                            Longitude:({4}, {5})", 
                                            radial.InnerText, 
                                            distance.InnerText,
                                            latitudeDegrees.InnerText,
                                            latitudeMinutes.InnerText,
                                            longitudeDegrees.InnerText,
                                            longitudeMinutes.InnerText));
        }
    }
}

You could do this only C#, but this is done much easier in XSLT and .NET has an excellent XSLT processor built in. XSLT is an open standard and specifically designed to transform XML to another format of XML (or HTML or text).

The input XSLT looks like this, save it as removeelement.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:param name="Radial"/>
    <xsl:output indent="yes" />

    <xsl:template match="TrafficPattern">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="WayPoint[not(Radial = $Radial)]" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Calling this from C# on your input is easy. The XSLT currently contains one parameter, Radial , but you can expand that to whatever you need to select the nodes to be deleted, the code speaks largely for itself. Here's an example to call the XSLT with your input XML (called input.xml):

// Load the xslt stylesheet:
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("removeelement.xslt");

// Create the XsltArgumentList with param
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddParam("Radial", "", "090");

// do the transformation on your input (can also use Stream or TextWriter)
using (XmlWriter w = XmlWriter.Create("output-with-removed-element.xml"))
{
    xslt.Transform("input.xml", xslArg, w);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM