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

本文关键字:查询 XML 命名空间 非标准 Linq | 更新日期: 2023-09-27 18:26:44

我正在尝试查询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);

我希望我有一个大致的想法。

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

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

正如您正确识别的那样,代码的主要问题是 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"));