使用C#和Linq按属性返回元素值

时间:2014-11-11 21:47:49

标签: c# xml linq

我非常擅长使用LINQ。我有以下XML:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <RetentionValue code="NR" fullName="Normal Retention">Used for normal retention periods commonly expressed as only numbers (i.e. "25" for 25 years).</RetentionValue>
  <RetentionValue code="SR" fullName="Short Retention">Used for short retention periods expressed in terms of months (i.e. "6 months").</RetentionValue>
  <RetentionValue code="AR" fullName="Annual Review">Review annually and retain what is needed, dispose of what is not needed.</RetentionValue>
  <RetentionValue code="PE" fullName="Permanent">Document is to be retained permanently.</RetentionValue>
  <RetentionValue code="EX" fullName="Expiration">Disposal date is calculated from expiration of a contract, loan, or other such instrument.</RetentionValue>
  <RetentionValue code="LI" fullName="Lifetime">Disposal date is calculated from the end-of-life date for a piece of equipment or other asset (e.g. software application).</RetentionValue>
  <RetentionValue code="TE" fullName="Employee Termination">Disposal date is calculated from the date of termination or retirement of an employee.</RetentionValue>
  <RetentionValue code="FR" fullName="Final Resolution">Disposal date is calculated from the date of final resolution for an issue.</RetentionValue>
</root>

在我的代码中,我创建了一个具有属性RetentionEvent的对象,其值为上面两个字母代码之一。我想找到具有匹配属性的Element,然后将fullName返回到一个文本字段,将值(wordy description)返回到另一个文本字段。到目前为止,我有以下内容:

// Construct a RecordDisposal object by passing it a valid retention code.
// An exception will be thrown if the code is not valid.
_rd = new RecordDisposal(RetentionCode.Text);
// Load up XML file with description of codes.
XDocument rangeValues = XDocument.Load("DisposalRangeValues.xml");
XElement codeValue = rangeValues.Root.Elements().Single(x => (string)x.Attribute("code") == _rd.DisposalList[0].RetentionEvent);
CodeName.Text = codeValue.Attribute("fullName").Value.ToString();
CodeDescription.Text = codeValue.Value.ToString();

查询是this代码的直接模式(我认为),但是我遇到了一些我不理解的错误:“查询正文必须以select子句结束或者一个组子句“(我认为这是ToList()的用途),而”select子句中表达式的类型是不正确的。在调用'Select'时类型推断失败。“不幸的是,我不太了解Linq对此进行故障排除,并且”对此错误的帮助“没有提供任何帮助。

我做错了什么?另外,我怀疑ToList()函数会在ToString()函数中返回一些不能很好地呈现的东西,但我还在等待弄清楚其他东西。如果有人有任何建议,请提供。

编辑:根据以下建议修改代码以使用Single。发现rangeValues正在将所有<root>作为单个节点加载。

EDIT2:想出来了。修改后的代码代替使用rangeValues.Root.Elements()。更新了上面的代码以反映。

2 个答案:

答案 0 :(得分:1)

您的.ToList()调用是正确的,但LINQ查询的语法不正确。

试试这个:

List<XElement> fullnames = (from fullName in rangeValues.Elements()
                            where fullName.Attribute("code") == _rd.DisposalList[0].RetentionEvent
                            select fullName).ToList();

答案 1 :(得分:1)

稍微重新格式化,您的代码如下所示:

XElement codeValue =
    from fullName
    in rangeValues.Elements()
                  .Where(x => (string)x.Attribute("code") == _rd.DisposalList[0].RetentionEvent)
                  .ToList();
    // select ???

因此ToList()已应用于您的查询的in部分,但您错过了select声明。

实际上,由于您希望返回单个XElement,您可能需要这样的内容,它会选择集合中唯一与Single()中指定的子句相匹配的元素:< / p>

XElement codeValue =
    (from fullName in rangeValues.Elements()
     where (string)fullName.Attribute("code") == _rd.DisposalList[0].RetentionEvent
     select fullName).Single();

备用语法(以上是查询语法,以下称为方法语法):

XElement codeValue =
    rangeValues.Elements().Single(x => (string)x.Attribute("code") == _rd.DisposalList[0].RetentionEvent);

如果可能不匹配,或者可能不止一个,那么您也想研究SingleOrDefault()First()FirstOrDefault()

相关问题