如何从XDocument中的节点获取元素,其中已知其他两个元素

时间:2011-10-01 19:37:20

标签: c# .net-3.5 elements linq-to-xml

我再次对XDocument / Linq的误解感到难过。对于下面的XML,我在代码中将nameEnprovinceCode作为变量。我正在尝试识别code(例如,s0000002)和nameFr,因为我有其他两个元素。 provinceCodeNameEn组合在XML中是唯一的(无重复)。

<siteList>
  <site code="s0000001">
    <nameEn>Edmonton</nameEn>
    <nameFr>Edmonton</nameFr>
    <provinceCode>AB</provinceCode>
  </site>
  <site code="s0000002">
    <nameEn>Algonquin Park</nameEn>
    <nameFr>Parc Algonquin</nameFr>
    <provinceCode>ON</provinceCode>
  </site>
...
</siteList>

这是我正在尝试的代码(我的XML在“已加载”的XDocument中:

selectedProvince = "ON";
selectedCity = "Algonquin Park";      
strSiteCode = loaded.Descendants("site")
    .Where(x => x.Element("provinceCode").Value == selectedProvince)
    .Where(x => x.Element("nameEn").Value == selectedCity)
    .Select(x => x.Element("code").Value)
    .ToString();
strNameFR = loaded.Descendants("site")
    .Where(x => x.Element("provinceCode").Value == selectedProvince)
    .Where (x => x.Element("nameEn").Value == selectedCity)
    .Select(x => x.Element("nameFr").Value)
    .ToString();

字符串strSiteCode返回:System.Linq.Enumerable+WhereSelectEnumerableIterator 2 [System.Xml.Linq.XElement,System.String] and strNameFR returns“”`。

我无法弄清楚工作代码应该是什么样子。谢谢你的帮助。

道格

3 个答案:

答案 0 :(得分:1)

尝试

var result = loaded.Descendants("site")
    .Where(x => (x.Element("provinceCode").Value == selectedProvince) &&
                 (x.Element("nameEn").Value == selectedCity) )
    .Select(x => x.Element("code").Value)
    .SingleOrDefault();

if (result != null)
{
    strSiteCode = result.ToString();
}

Select()调用返回一个集合(在您的情况下恰好只有一个元素)。因此,您必须致电SingleOrDefault()(或Single())才能获得该项目。此外,我删除了第二个Where()并将条件包含在第一个Where()

答案 1 :(得分:1)

请记住,“x.Element(...)”方法可能会返回null,因此在其上访问“Value”将导致null ref。这假设您的xml可能总是具有provinceCode或nameEn。如果是这样,你就不会有问题,但是你不想在发布代码中放置那个可能的null ref ex。以下解决了null ref问题。

var site = loaded
    .Descendants("site")
    .FirstOrDefault(x => (string)x.Element("provinceCode") == selectedProvince &&
                    x => (string)x.Element("nameEn") == selectedCity);    

if (site == null)
{
    return
}

var siteCode = (string)site.Attribute("code");
var nameFr = (string)site.Element("nameFr");

答案 2 :(得分:0)

我可能会这样重写:

  • 获取一次匹配的<site>节点列表
  • 迭代所有匹配(通常只有一个)
  • 从这些匹配项中获取code 属性nameFr元素

代码看起来像这样:

// determine the matching list of <site> nodes ...
var selectedSites = loaded
                       .Descendants("site")
                       .Where(x => x.Element("provinceCode").Value == selectedProvince)
                       .Where(x => x.Element("nameEn").Value == selectedCity);

// iterate over all matching <site> nodes
foreach (var site in selectedSites)
{
    // grab the code attribute and nameFr element from <site> node
    var siteCode = site.Attribute("code").Value;
    var nameFR = site.Element("nameFr").Value;
}