C#根据不需要的属性值列表从XMLDocument中删除整个元素

时间:2014-11-13 21:12:46

标签: c# xpath xmldocument

我有一个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;它,但我不能帮助感觉可能有更好的方式。

希望你能帮忙!

3 个答案:

答案 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();
    }
}