如何在包含特定元素值的XElement之间删除特定XElement
本文关键字:XElement 之间 删除 元素 包含特 | 更新日期: 2023-09-27 18:22:28
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受到影响。。。
是一个简单的天真解决方案
var elements = Xd.XPathSelectElements("/pfsense/nat//rule[descr/text() = 'delete this']");
elements.Remove();
这样的东西应该可以工作:
xd.Element("pfsense").Elements("nat").Elements("rule").Elements("descr").Where(x => x.Value == "delete this").Remove();
通过使用Where
和Any
,如:
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)));
这应该对您有效;
正如你可能知道的,元素有一个级别。如果你想做这样的事情,最好使用后代。需要注意的另一点是"Equal"运算符的使用。您可以使用contains,但使用"delete"answers"donnotdelete"这样的值风险太大。另外请注意,即使您有CDATA,它们也不会出现在"Value"中。
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();