删除XML节点集合中的空/空白元素

时间:2013-01-24 19:28:29

标签: c# linq-to-xml xelement

我有一个这样的XML文档:

<magento_api>
    <data_item>
        <code>400</code>
        <message>Attribute weight is not applicable for product type Configurable Product</message>
    </data_item>
    <data_item>
        <code>400</code>
        <message>Resource data pre-validation error.</message>
    </data_item>
    <data_item>
        <code>1</code>
        <message></message>
    </data_item>
    <data_item>
        <code></code>
        <message>No code was given</message>
    </data_item>
</magento_api>

我正在尝试迭代每个节点并执行以下操作:

  1. 丢弃任何空/空白的元素。
  2. 仅使用包含值的元素生成新节点。
  3. 将生成的文档发送到其他Web服务。
  4. 我正在努力解决的问题是如何遍历每个节点并检查每个元素的空值。

    我一直在http://rextester.com/runcode测试这段代码,但似乎无法弄明白:

    Console.WriteLine("Querying tree loaded with XElement.Load");
    Console.WriteLine("----");
    XElement doc = XElement.Parse(@"<magento_api>
              <data_item>
                <code>400</code>
                <message>Attribute weight is not applicable for product type Configurable Product</message>
              </data_item>
              <data_item>
                <code>400</code>
                <message>Resource data pre-validation error.</message>
              </data_item>
              <data_item>
                <code>1</code>
                <message></message>
              </data_item>
              <data_item>
                <code></code>
                <message>No code was given</message>
              </data_item>
        </magento_api>");
    
    int counter = 1;
    IEnumerable<XNode> nodes =
        from nd in doc.Nodes()
        select nd;
    foreach (XNode node in nodes)
    {
        Console.WriteLine(counter + "-" + node);
        IEnumerable<XElement> elements =
        from el in node //this is where I've been trying various methods, but no dice.
        select el;
        foreach (XElement e in elements)
        {
               Console.WriteLine(counter + "-" + e.Name + "-" + e.Value + "\r\n");
        }
        counter++;
    }
    

    基于上面的XML输入,我希望得到以下输出:

    <magento_api>
        <data_item>
            <code>400</code>
            <message>Attribute weight is not applicable for product type Configurable Product</message>
        </data_item>
        <data_item>
            <code>400</code>
            <message>Resource data pre-validation error.</message>
        </data_item>
        <data_item>
            <code>1</code>
        </data_item>
        <data_item>
            <message>No code was given</message>
        </data_item>
    </magento_api>
    

    我不确定我是否使用正确的方法迭代节点和元素。

3 个答案:

答案 0 :(得分:31)

单个单行可以完成工作,无需迭代所有元素。在这里:

doc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove();

<强>测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    public class TestRemove
    {
        public static void Main() {
            Console.WriteLine("----OLD TREE STARTS---");
            XElement doc = XElement.Parse(@"<magento_api>
                                              <data_item>
                                                <code>400</code>
                                                <message>Attribute weight is not applicable for product type Configurable Product</message>
                                              </data_item>
                                              <data_item>
                                                <code>400</code>
                                                <message>Resource data pre-validation error.</message>
                                              </data_item>
                                              <data_item>
                                                <code>1</code>
                                                <message></message>
                                              </data_item>
                                              <data_item>
                                                <code></code>
                                                <message>No code was given</message>
                                              </data_item>
                                        </magento_api>");
            Console.Write(doc.ToString());
            Console.WriteLine("");
            Console.WriteLine("----OLD TREE ENDS---");
            Console.WriteLine("");
            doc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove();
            Console.WriteLine("----NEW TREE STARTS---");
            Console.Write(doc.ToString());
            Console.WriteLine("");
            Console.WriteLine("----NEW TREE ENDS---");
            Console.ReadKey();
        }
    }
}

还可以对其进行测试here

答案 1 :(得分:5)

doc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove(); 

这一行不会抛出充满空子标签的空父标签。它只会移除他们的孩子,这可能适合您的情况,也可能不适合您的情况。实现这一目标是一个非常简单的变化,您只需要首先从最低级别开始删除。像

这样的东西
foreach(XElement child in doc.Descendants().Reverse())
{
    if(!child.HasElements && string.IsNullOrEmpty(child.Value) && !child.HasAttributes) child.Remove();
}

感谢Nyerguds的属性建议。

答案 2 :(得分:1)

在VB中我需要再次找到它:

doc.Descendants().Where(Function(e) String.IsNullOrEmpty(e.Value)).Remove()