Linq使用非标准命名空间查询XML

时间:2014-10-15 23:37:23

标签: c# xml linq

我正在尝试查询XML文件,但某些节点有名称空间,其他节点没有导致永远无法获得完整的解决方案。

我想知道如果没有Xpath可以做到这一点吗?

XML

<Household name="Home" xmlns="AP:CB" description="Home" >
    <InsuranceClaims/>
    <mortgages>
        <mortgage id="Sally Mae"  xmlns="AP:CB" />
    </mortgages>
    <Appliances>
        <Appliance key="Stove" value="5000"  />
    </Appliances>
    <Persons>
        <Person name="Henry" age="35" />
        <Person name="Jill" age="23" xmlns="AP:CB"/>
    </Persons>
</Household>

所以我们有一个AP命名空间:CB存在于某些元素而不是其他元素上。

我目前的尝试没有产生任何结果。

_Household = _XDoc.Descendants()
                  .Where(x => x.Name == "Persons")
                  .Select(x => new
                         {
                             name = (string)x.Element( "Person").Attribute("name").Value,
                             age = (string)x.Element("Person").Attribute("age").Value
                         })
                 .ToDictionary(x => x.age, x => x.name);

我希望我的总体思路正确。

编辑:更新的captialization以匹配区分大小写,结果相同。  添加值并将where子句更改为后代括号不起作用。

1 个答案:

答案 0 :(得分:2)

正确识别的代码的主要问题是XML命名空间。虽然您错误的是代码中的某些元素包含它们而某些元素却没有:子节点从其父节点继承xmlns声明,这意味着文档中的所有元素都在同一个命名空间中。

在具有命名空间的文档上使用LINQ to XML时,必须明确指定该命名空间:

XNamespace ns = "AP:CB";

…

_Household = _XDoc.Descendants()
                  .Where(x => x.Name == ns + "Persons")
                  .Select(x => new
                         {
                             name = (string)x.Element(ns + "Person").Attribute("name").Value,
                             age = (string)x.Element(ns + "Person").Attribute("age").Value
                         })
                  .ToDictionary(x => x.age, x => x.name);

虽然此代码只返回一个值(对于Henry),因为您选择了所有Persons元素,并为每个元素选择其第一个Person子节点。

相反,我会写这样的查询:

_Household = _XDoc.Descendants(ns + "Persons")
                  .Elements(ns + "Person")
                  .ToDictionary(x => (int)x.Attribute("age"), x => (string)x.Attribute("name"));