如何在包含特定元素值的XElements之间删除特定的XElement

时间:2015-11-18 00:17:26

标签: c# linq xpath xelement

Xdocument Xd(从xml文件映射):

<pfsense>
  <nat>
    <outbound>
      <mode>advanced</mode>
    </outbound>
    <rule>
      <source>
        <any />
      </source>
      <destination>
        <network>wanip</network>
        <port>63350</port>
      </destination>
      <protocol>tcp</protocol>
      <target>10.100.100.15</target>
      <local-port>11</local-port>
      <interface>wan</interface>
      <descr><![CDATA[delete this]]></descr>
      <associated-rule-id />
    </rule>

    <rule>
      <source>
        <any />
      </source>
      <destination>
        <network>wanip</network>
        <port>63350</port>
      </destination>
      <protocol>tcp</protocol>
      <target>10.100.100.11</target>
      <local-port>11</local-port>
      <interface>wan</interface>
      <descr><![CDATA[don't delete this]]></descr>
      <associated-rule-id />
    </rule>
  </nat>
</pfsense>

我想只删除具有以下描述的规则元素:

<descr><![CDATA[delete this]]></descr>

预期结果是相同的XDocument(Xd),没有将要删除的条件的XElement。我试过这个:

XElement ruleToDelete = null;

foreach (var x in Xd.Root.Element("nat").Elements("rule"))
{
    if (x.Element("descr")!= null && x.Element("descr").Value == ruleDescription)
    {
        ruleToDelete = x;
        break;
    }
}

if (ruleToDelete != null)
{
    ruleToDelete.Remove();
    //But Xd is the same as before...
}

但是,我希望Xd受到影响......

4 个答案:

答案 0 :(得分:0)

这样的事情应该有效:

xd.Element("pfsense").Elements("nat").Elements("rule").Elements("descr").Where(x => x.Value == "delete this").Remove();

答案 1 :(得分:0)

一个简单的天真解决方案

var elements = Xd.XPathSelectElements("/pfsense/nat//rule[descr/text() = 'delete this']");
elements.Remove();

答案 2 :(得分:0)

使用WhereAny之类的:

Xd.Root.Element("nat").Elements("rule").Where
            (x => x.Elements("descr").Any(t => t.Value == ruleDescription)).Remove();

并验证结果:

        Assert.IsFalse(Xd.Root.Element("nat").Elements
            ("rule").Any(x => x.Elements("descr").Any(t => t.Value == ruleDescription)));

答案 3 :(得分:0)

这对你有用;

你可能知道Element有一个级别。如果你想做这样的事情,你最好使用后代。其他要注意的是使用“Equal”运算符。您可以使用包含,但使用“删除”和“不删除”等值时风险太大。另请注意,即使您有CDATA,它们也不会出现在“值”中。

class Program
{
    static void Main(string[] args)
    {
        var xdoc = XDocument.Load(@"C:\Xd.xml");
        Console.WriteLine("--------------------");
        Console.WriteLine("BEFORE");
        Console.WriteLine("--------------------");
        Console.WriteLine(xdoc.ToString());
        xdoc.Descendants().Where(d => d.Name.LocalName.Equals("descr") && d.Value.Equals("delete this")).Remove();
        Console.WriteLine("");
        Console.WriteLine("");
        Console.WriteLine("--------------------");
        Console.WriteLine("AFTER");
        Console.WriteLine("--------------------");
        Console.WriteLine(xdoc.ToString());
        Console.ReadLine();
    }
}

刚刚注意到你想删除“rule”元素。 所以你可以改变这样的查询。

   xdoc.Descendants().Where(d => d.Name.LocalName.Equals("rule") 
            && d.Descendants().Any(dd => dd.Name.LocalName.Equals("descr") && dd.Value.Equals("delete this"))).Remove();