用attribut“nil = true”清理Xml元素 - 创建linq版本?

问题描述:

我试图用文件内的attribut“nil = true”来清理Xml元素。 我想出了这个算法,但我不喜欢它的外观。用attribut“nil = true”清理Xml元素 - 创建linq版本?

有人知道这个算法的linq版吗?

/// <summary> 
    /// Cleans the Xml element with the attribut "nil=true". 
    /// </summary> 
    /// <param name="value">The value.</param> 
    public static void CleanNil(this XElement value) 
    { 
     List<XElement> toDelete = new List<XElement>(); 

     foreach (var element in value.DescendantsAndSelf()) 
     { 
      if (element != null) 
      { 
       bool blnDeleteIt = false; 
       foreach (var attribut in element.Attributes()) 
       { 
        if (attribut.Name.LocalName == "nil" && attribut.Value == "true") 
        { 
         blnDeleteIt = true; 
        } 
       } 
       if (blnDeleteIt) 
       { 
        toDelete.Add(element); 
       } 
      } 
     } 

     while (toDelete.Count > 0) 
     { 
      toDelete[0].Remove(); 
      toDelete.RemoveAt(0); 
     } 
    } 
+3

你的问题没有提及任何有关XML命名空间的内容,但http://www.w3.org/2001/XMLSchema-instance命名空间(通常使用前缀“xsi”)具有一个“nil”属性,您可以将其设置为“true” 。如果这是您使用的属性,它解释了为什么答案不能按预期工作。答案在默认名称空间中查找'nil'属性,并且不适用于您的XML。 – 2012-02-10 15:53:21

有什么nil属性的命名空间?把里面{}这样的:

public static void CleanNil(this XElement value) 
{ 
    value.Descendants().Where(x=> (bool?)x.Attribute("{http://www.w3.org/2001/XMLSchema-instance}nil") == true).Remove(); 
} 

这应该工作..

public static void CleanNil(this XElement value) 
{ 
    var todelete = value.DescendantsAndSelf().Where(x => (bool?) x.Attribute("nil") == true); 
    if(todelete.Any()) 
    { 
     todelete.Remove(); 
    } 
} 
+0

抱歉不起作用! – frankyt79 2012-02-10 13:40:37

+0

你有什么错误? – Flowerking 2012-02-10 13:48:21

扩展方法:

public static class Extensions 
{ 
    public static void CleanNil(this XElement value) 
    { 
     value.DescendantsAndSelf().Where(x => x.Attribute("nil") != null && x.Attribute("nil").Value == "true").Remove(); 
    } 
} 

使用范例:

File.WriteAllText("test.xml", @" 
       <Root nil=""false""> 
        <a nil=""true""></a> 
        <b>2</b> 
        <c nil=""false""> 
         <d nil=""true""></d> 
         <e nil=""false"">4</e> 
        </c> 
       </Root>"); 
var root = XElement.Load("test.xml"); 
root.CleanNil(); 
Console.WriteLine(root); 

输出:

<Root nil="false"> 
    <b>2</b> 
    <c nil="false"> 
    <e nil="false">4</e> 
    </c> 
</Root> 

如您所见,节点<a><d>按预期方式移除。唯一要注意的事情是,你不能调用<Root>节点上的这种方法,因为根节点不能被删除,你会得到这个运行时错误:

The parent is missing.

+0

抱歉不起作用! – frankyt79 2012-02-10 13:40:42

+0

@ frankyt79你是什么意思,它不起作用?我为答案添加了一个工作示例。我测试了它,它工作。 – Meysam 2012-02-10 15:40:15

我改变我的方式来解决这一问题,并避免在我的空类型 创建无我用下面的

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer%28v=vs.90%29.aspx

public class OptionalOrder 
    { 
     // This field should not be serialized 
     // if it is uninitialized. 
     public string FirstOrder; 

     // Use the XmlIgnoreAttribute to ignore the 
     // special field named "FirstOrderSpecified". 
     [System.Xml.Serialization.XmlIgnoreAttribute] 
     public bool FirstOrderSpecified; 
    }