c#xml element()选择未定义的元素

时间:2009-10-15 13:36:32

标签: c# xml linq

我创建了以下xml

    <Fields xmlns="http://tempuri.org/XMLSchema1.xsd:Fields">
         <Field Name="ServiceProviderName">    
               <ID>0</ID>      
         </Field>   
         <Field Name="TransactionNumber">    
               <ID>1</ID>
               <Padding Length="8" PadChar="0"/>
               <MaxLength>10</MaxLength>
         </Field>   
         <Field Name="Sim">    
              <ID>2</ID>
              <Head>8927</Head>
              <Padding Length="15" PadChar="0"/>   
         </Field> 
     </Fields>

我正在尝试使用linq将其分配给对象。我已经定义了一个名为N2NField的对象

var xe = (from root in xdb.Descendants(NameSpace + "Field") 
where root.Attribute("Name").Value.Equals(Name)                                      
select new N2NField
{
            Name = root.Attribute("Name").Value,
            ID = int.Parse(root.Element(NameSpace+"ID").Value),
            Default = root.Element(NameSpace + "Default").Value,
            Head = root.Element(NameSpace + "Head").Value,
            Tail = root.Element(NameSpace + "Tail").Value,
            MinLength = int.Parse(root.Element(NameSpace + "MinLength").Value),
            MaxLength = int.Parse(root.Element(NameSpace + "MaxLength").Value)                                           

                                       }).First();

我在搜索Name =“Sim”时得到一个未设置为对象错误实例的对象。我知道这种情况正在发生,因为在像Tail,MinLength,MaxLength等的xml字段中还没有设置。这是合乎逻辑的,因为我的xsd定义了那些minoccurrences设置为0.理论上,xml中会有一些字段包含一些字段而没有其他字段且具有必填字段。

有没有办法检查字段是否存在以及它们是否没有为这些属性将对象N2NField值指定为null?我不想被迫在xsd中强制要求所有字段。任何想法?

编辑 - N2N字段类

public class N2NField { 
   public string Name { get; set; } 
   public int ID { get; set; } 
   public string Default { get; set; } 
   public string Head { get; set; } 
   public string Tail { get; set; } 
   public int MinLength { get; set; } 
   public int MaxLength { get; set; } 
 }

4 个答案:

答案 0 :(得分:2)

似乎你的XML中没有一些节点;请注意我删除了.Value属性并添加了一个强制转换为字符串。

var xe = (from root in xdb.Descendants(NameSpace + "Field")
          where root.Attribute("Name").Value.Equals("Sim")
          select new N2NField
          {
              Name    = (string)root.Attribute("Name"),
              ID      = int.Parse((string)root.Element(NameSpace + "ID") ?? "0"),
              Default = (string)root.Element(NameSpace + "Default"),
              Head    = (string)root.Element(NameSpace + "Head"),
              Tail    = (string)root.Element(NameSpace + "Tail"),
              MinLength = int.Parse((string)root.Element(NameSpace + "MinLength") ?? "0"),
              MaxLength = int.Parse((string)root.Element(NameSpace + "MaxLength") ?? "0")
          }).First();

HTH

答案 1 :(得分:0)

我一直在搞乱这个想法,它似乎对我有用

XElement xdb = XElement.Load(XMLPath);
            XNamespace NameSpace = xdb.Name.Namespace;

            var xe = (from root in xdb.Descendants(NameSpace + "Field")
                           where root.Attribute("Name").Value.Equals(Name)                                       
                           select new N2NField
                                       {
                                           Name = root.Attribute("Name").Value,
                                           ID = int.Parse(root.Element(NameSpace+"ID").Value),
                                           Default = root.Descendants(NameSpace + "Default").Any() ? root.Element(NameSpace + "Default").Value : null,
                                           Head = root.Descendants(NameSpace+"Head").Any() ? root.Element(NameSpace + "Head").Value : null,
                                           Tail = root.Descendants(NameSpace+"Tail").Any() ? root.Element(NameSpace + "Tail").Value : null,
                                           MinLength = root.Descendants(NameSpace+"MinLength").Any()  ? int.Parse(root.Element(NameSpace + "MinLength").Value) : -1,
                                           MaxLength = root.Descendants(NameSpace+"MaxLength").Any() ? int.Parse(root.Element(NameSpace + "MaxLength").Value) : -1                                           

                                       }
                                       ).First();

通过检查元素是否首先存在于Descendants()。Any()它允许我在代码级别分配默认值(如果节点不存在)。

答案 2 :(得分:0)

这比使用Descendants()。Any()方法更有效。这只是检查你正在寻找的那个是否为空,如果它没有赋值。

var xe = (from root in xdb.Descendants(NameSpace + "Field")
          where root.Attribute("Name").Value.Equals(Name)
          select new N2NField
          {
              Name = root.Attribute("Name").Value,
              ID = int.Parse(root.Element(NameSpace + "ID").Value),
              Default = root.Element(NameSpace + "Default") == null ? root.Element(NameSpace + "Default").Value : null,
              Head = root.Element(NameSpace + "Head") == null ? root.Element(NameSpace + "Head").Value : null,
              Tail = root.Element(NameSpace + "Tail") == null ? root.Element(NameSpace + "Tail").Value : null,
              MinLength = root.Element(NameSpace + "MinLength") == null ? int.Parse(root.Element(NameSpace + "MinLength").Value) : -1,
              MaxLength = root.Element(NameSpace + "MaxLength") == null ? int.Parse(root.Element(NameSpace + "MaxLength").Value) : -1

          }).First();

答案 3 :(得分:0)

我知道这是一个非常古老的回复,但我从谷歌那里得到了这个问题,并为我的问题找到了一个不同的解决方案。

var xe = (from root in xdb.Descendants(NameSpace + "Field")
          where root.Attribute("Name").Value.Equals(Name)
          select new N2NField
          {
              Name = root.Attribute("Name").Value,
              ID = int.Parse(root.Element(NameSpace + "ID").Value),
              Default = root.Elements(NameSpace + "Default").Any ? root.Element(NameSpace + "Default").Value : null,
              Head = root.Elements(NameSpace + "Head").Any ? root.Element(NameSpace + "Head").Value : null,


          }).First();

这适用于我的情况,其中跟随Brians的例子给了我同样的错误。