我有一个XML文件,例如
<Bars1>
<Bar name='0'>245</Bar>
<Bar name='1'>180</Bar>
<Bar name='2'>120</Bar>
<Bar name='3'>60</Bar>
<Bar name='4'>0</Bar>
</Bars1>
<Bars2>
<Bar name='0'>25</Bar>
<Bar name='1'>10</Bar>
<Bar name='2'>10</Bar>
<Bar name='3'>6</Bar>
<Bar name='4'>0</Bar>
</Bars2>
<Gubbins3>
<Bar name='0'>45</Bar>
<Bar name='1'>18</Bar>
<Bar name='2'>12</Bar>
<Bar name='3'>4</Bar>
<Bar name='4'>0</Bar>
</Gubbins3>
和List<int>
notNeededBarNames,包含例如{1,3}
我已将XML文件加载到XmlDocument
xmlDoc中,并希望删除任何&#34; Bar&#34;元素所在的属性&#34; name&#34;是我列表中的整数之一,无论它在XML中可能存在于何处。我的例子很小,但实际上文档和列表可能非常大。
这样做有一个很好的方法吗?我可以&#34;蛮力&#34;它,但我不能帮助感觉可能有更好的方式。
希望你能帮忙!
答案 0 :(得分:6)
Linq2Xml可以让生活更轻松。
var notNeededBarNames = new List<int>() { 1, 3 };
var xDoc = XDocument.Load(filename);
xDoc.Descendants("Bar")
.Where(bar => notNeededBarNames.Contains( (int)bar.Attribute("name")) )
.Remove();
var newXml = xDoc.ToString();
答案 1 :(得分:1)
对于基于xpath的解决方案,您可以选择要删除的节点,如下所示:
private static void TestXmlBars()
{
string s = @"<root>
<Bars1>...</Bars1>
<Bars2>...</Bars2>
<Gubbins3>...</Gubbins3>
</root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(s);
List<int> exclude = new List<int>{1,2};
// create comma-delimited list
string list = "," + String.Join(",", exclude) + ",";
string xpath = String.Format("/root/*/Bar[contains('{0}', concat(',', @name, ','))]", list);
XmlNodeList nodesToExclude = doc.SelectNodes(xpath);
foreach (XmlNode node in nodesToExclude)
{
node.ParentNode.RemoveChild(node);
}
Console.WriteLine(doc.OuterXml);
}
(请注意,xpath 1受限制,因为它没有'in'功能,因此'contains'解决方法 - 请参阅XPath 1.0 to find if an element's value is in a list of values)
答案 2 :(得分:0)
这样的东西会起作用
using System;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
class Program
{
static void Main()
{
var notNeededBarNames = new[] {1, 3};
var elems = new[] {"Bars1", "Bars2", "Gubbins3"};
var newXDoc = new XElement("root");
var xDoc = XDocument.Load("PathToYourXmlFile");
foreach (var elem in elems)
{
newXDoc.Add(new XElement(elem));
var curElem = newXDoc.Elements(elem).Single();
string xpath = String.Format("root/{0}/Bar", elem);
var childElems = xDoc.XPathSelectElements(xpath);
foreach (var childElem in childElems)
{
bool add = true;
var nameAtt = childElem.Attribute("name");
if (nameAtt != null)
{
int val = Convert.ToInt32(nameAtt.Value);
if (notNeededBarNames.Any(x => x == val))
{
add = false;
}
}
if (add)
{
curElem.Add(childElem);
}
}
}
var newXml = newXDoc.ToString();
}
}