C # Удаление целых элементов из XMLDocument на основе списка значений нежелательных атрибутов

1

У меня есть 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 и хочу удалить любой элемент "Bar", где атрибут "name" является одним из целых чисел из моего списка, независимо от того, где он может существовать в XML. Мой пример небольшой, но на самом деле документ и список могут быть довольно большими.

Есть ли хороший элегантный подход к этому? Я могу "переработать" его, но я не могу не чувствовать, что может быть лучший способ.

Надеюсь, ты поможешь!

  • 2
    I can "brute force" it сначала сделать, чем задать конкретную проблему о вашем коде.
Теги:
xpath
xmldocument

3 ответа

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

Для решения на основе 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 ограничен, поскольку он не имеет функции "в", следовательно, "содержит" обходной путь - см. XPath 1.0, чтобы узнать, находится ли значение элемента в списке значений)

  • 0
    Что такое ToStringElements ?
  • 0
    Смотрите в нижней части моего поста (не уверен, почему он остался в предыдущей строке - я буду редактировать его, чтобы быть более заметным)
Показать ещё 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();
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню