Удалить элемент без дочернего элемента - PullRequest
0 голосов
/ 16 марта 2020

Структура моего XML с использованием XElement выглядит следующим образом. Я использую XElement в XDocument

<?xml version='1.0' encoding='UTF-8'?>
<return xmlns:rmas="" xmlns:xsi="" xsi:noNamespaceSchemaLocation="">
  <header>
    [...]
  </header>
  <body>
     <scheme>
        [...]
        <data>
          <serial-no>1</serial-no>
          <employment>1</employment>
          <code>1234</code>
        </data>
        <data />
        <data />
     </scheme>
     <scheme>
        [...]
        <data>
          <serial-no>1</serial-no>
          <employment>1</employment>
          <code>1234</code>
        </data>
        <data />
        <data />
     </scheme>
     <scheme>
        [...]
        <data>
          <serial-no>1</serial-no>
          <employment>1</employment>
          <code>1234</code>
        </data>
        <data />
        <data />
     </scheme>
  </body>
</return>

Я хотел бы удалить все элементы данных без дочерних элементов, т.е. <data /> элементов. Вот мой код

 foreach (XElement scheme in doc.Descendants("scheme"))
 {
            //copy an existing node as template for new data node.
            XElement newData = XElement.Parse(scheme.Element("data").ToString());
            newData.Element("serial-no").SetValue("abc1234");
            newData.Element("employment").SetValue("PUZAD-452");
            newData.Element("code").SetValue(codeValue);


            XElement newData2 = XElement.Parse(scheme.Element("data").ToString());
            newData2.Element("serial-no").SetValue("abc1234");
            newData2.Element("employment").SetValue("PUZAD-452");
            newData2.Element("code").SetValue(codeValue);


            XElement newData3 = XElement.Parse(scheme.Element("data").ToString());
            newData3.Element("serial-no").SetValue("abc1234");
            newData3.Element("employment").SetValue("PUZAD-452");
            newData3.Element("code").SetValue(codeValue);

            if (getGlobalScheme1 == "1111")
            {
                if ((string)(scheme.Descendants("code").First()) == "1111")
                {
                    newData2.RemoveAll();
                    newData3.RemoveAll();
                }
                scheme.Add(newData);
            }
            if (getGlobalScheme2 == "2222")
            {
                if ((string)(scheme.Descendants("code").First()) == "2222")
                {
                    newData.RemoveAll();
                    newData3.RemoveAll();
                }
                scheme.Add(newData2);
            }

            if (getGlobalScheme3 == "3333")
            {
                if ((string)(scheme.Descendants("code").Last()) == "3333")
                {
                    newData.RemoveAll();
                    newData2.RemoveAll();
                }
                scheme.Add(newData3);
            }
}

Как мне достичь своей цели удаления элементов <data /> без дочерних элементов. Я ломал голову вокруг этого, но безрезультатно.

Ответы [ 2 ]

0 голосов
/ 17 марта 2020

(1) Позволяет сохранить XML в виде файла в файловой системе.

(2) Мы создадим список List<XElement> из SCHEME узлов.

(3) Выполнить итерацию по списку SCHEME узлов и удалить DATA элементы без дочерних элементов.

(4) Сохранить измененное XML обратно в файл .

XML Файл

<?xml version="1.0" encoding="UTF-8"?>
<return xmlns:rmas="someURI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="fafa.xsd">
    <header>[...]</header>
    <body>
        <scheme>
            <data>
                <serial-no>1</serial-no>
                <employment>1</employment>
                <code>1234</code>
            </data>
            <data/>
            <data/>
        </scheme>
        <scheme>
            <data>
                <serial-no>1</serial-no>
                <employment>1</employment>
                <code>1234</code>
            </data>
            <data/>
            <data/>
        </scheme>
        <scheme>
            <data>
                <serial-no>1</serial-no>
                <employment>1</employment>
                <code>1234</code>
            </data>
            <data/>
            <data/>
        </scheme>
    </body>
</return>

c#

void Main()
{
    const string fileName = @"e:\Temp\Delete.xml";
    const string SCHEME = "scheme";
    const string DATA = "data";

    XDocument xdoc = XDocument.Load(fileName);

    // create list of SCHEME nodes
    List<XElement> nodes = xdoc.Descendants(SCHEME).ToList();

    // iterate through list of SCHEME nodes and delete DATA elements without children.
    foreach (XElement node in nodes)
        node.Elements(DATA).Where(n => n.DescendantNodes().Count() == 0).Remove();

    // end result
    Console.WriteLine(xdoc);

    // save back
//  xdoc.Save(fileName);
}

Выход XML

<return xmlns:rmas="someURI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="fafa.xsd">
    <header>[...]</header>
    <body>
        <scheme>
            <data>
                <serial-no>1</serial-no>
                <employment>1</employment>
                <code>1234</code>
            </data>
        </scheme>
        <scheme>
            <data>
                <serial-no>1</serial-no>
                <employment>1</employment>
                <code>1234</code>
            </data>
        </scheme>
        <scheme>
            <data>
                <serial-no>1</serial-no>
                <employment>1</employment>
                <code>1234</code>
            </data>
        </scheme>
    </body>
</return>
0 голосов
/ 16 марта 2020

Я постараюсь ответить на этот вопрос.

Попробуйте добавить элементы, у которых есть дочерние элементы, в массив, затем выполните итерации по этому.

Дайте следующему go, используйте его перед foreach оператор:

    var nodes = doc.Descendants("scheme").Where(x => x.Element("data") != null).ToList();

Кроме того, вы можете попробовать с совершенно противоположными логами c, проверив, имеет ли узел, который вы сейчас просматриваете, дочерний с этим фрагментом кода:

    YourXmlNode.ChildNodes.OfType<XmlElement>().Any()

Я также добавляю несколько ссылок на статьи и ответы, которые, как я считаю, помогут вам разобраться в вашей проблеме.

...