【问题标题】:LINQ request for getting the furthest xml child node with an attribute获取具有属性的最远 xml 子节点的 LINQ 请求
【发布时间】:2015-06-05 14:41:53
【问题描述】:

我有一个定义项目/位置类别的 xml 文件,它们的 id 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Eve_App>
    <Item_Types>
        <Ore>
            <Arkonor>
                <Arkonor ID="22"/>
                <Compressed_Arkonor ID="28367"/>
                <Compressed_Crimson_Arkonor ID="28385"/>
                <Compressed_Prime_Arkonor ID="28387"/>
                <Crimson_Arkonor ID="17425"/>
                <Prime_Arkonor ID="17426"/>
            </Arkonor>

            <Bistot>
                <Bistot ID="1223"/>
                <Compressed_Bistot ID="28388"/>
                <Compressed_Monoclinic_Bistot ID="28389"/>
                <Compressed_Triclinic_Bistot ID="28390"/>
                <Monoclinic_Bistot ID="17429"/>
                <Triclinic_Bistot ID="17428"/>
            </Bistot>

            <Crokite>
                <Compressed_Crokite ID="28391"/>
                <Compressed_Crystalline_Crokite ID="28392"/>
                <Compressed_Sharp_Crokite ID="28393"/>
                <Crokite ID="1225"/>
                <Crystalline_Crokite ID="17433"/>
                <Sharp_Crokite ID="17432"/>
            </Crokite>
            ...
        </Ore>

        <Ice>
            <Blue_Ice ID="16264"/>
            <CLear_Icicle ID="16262"/>
            <Compressed_Blue_Ice ID="28433"/>
            ...
        </Ice>

        <Gas>
            <Booster_Gas_Clouds>
                <Amber_Cytoserocin ID="25268"/>
                <Amber_Mykoserocin ID="28694"/>
                <Azure_Cytoserocin ID="25279"/>
                <Azure_Mykoserocin ID="28695"/>
                <Celadon_Cytoserocin ID="25275"/>
                <Celadon_Mykoserocin ID="28696"/>
                ...
            </Booster_Gas_Clouds>

            <Fullerenes>
                <Fullerite_C28 ID="30375"/>
                <Fullerite_C32 ID="30376"/>
                ...
            </Fullerenes>
        </Gas>

        <Mineral>
            <Isogen ID="37"/>
            <Megacyte ID="40"/>
            <Mexallon ID="36"/>
            <Morphite ID=""/>
            <Nocxium ID="38"/>
            <Pyerite ID="35"/>
            <Tritanium ID="34"/>
            <Zydrine ID="39"/>
        </Mineral>
...

如您所见,包含ID 的项目不一定在同一级别。我想知道是否有一个 LINQ 请求可以让我获得与 ID 关联的节点的名称,我希望独立于 Item_Types 节点中该项目的级别。

编辑:

以下请求是否会在所有嵌套子节点中进行迭代?

IEnumerable<string> ids =
       from el in xelement.Elements("Item_Types")
       where (int)el.Attribute("ID") == "22" // For example
       select (string)el.value;

EDIT2:

目前我有这个:

IEnumerable<String> names = _xmlFile.Descendants()
    .Where(x => x.Attributes().Any(a => a.Name.LocalName == "ID") && uint.Parse(x.Attributes().First(a => a.Name.LocalName == "ID").Value) == id)
    .Select(t => t.Name.LocalName);

if (names.Count() != 0) // Error here
{
    return names.ElementAt(0);
}
else
{
    return "";
}

很遗憾,调用Count() 函数时出现以下错误:

Input string was not in a correct format.

当我查看names 变量的值时,我也可以在调试中看到此错误。虽然当我只是return names.ElementAt(0); 而不使用Count() 时不会发生这种情况(我能够正确地看到与ID 关联的名称),但是如果ID 不存在,我会得到另一个错误我尝试return names.ElementAt(0);(这就是我做那个检查的原因)。

为什么会出现上面提到的Parse() 错误?

【问题讨论】:

    标签: c# xml linq xml-parsing linq-to-xml


    【解决方案1】:

    试试这个:

        IEnumerable<string> ids = xelement.Descendants()
    .Where(x => x.Attributes().Any(a => a.Name.LocalName == "ID") && x.Attributes().First(a => a.Name.LocalName == "ID").Value == "28390")
    .Select(t => t.Name.LocalName);
    

    首先,我在后代节点中检查 ID 属性是否存在,如果存在,我检查它的值是否需要 ID。

    【讨论】:

    • 所以基本上Descendants 让我们可以访问根元素的所有子节点,并且查询会检查每个节点?
    • 只是想补充一点,为了使这个答案起作用,您必须将x.Attributes().First(a =&gt; a.Name.LocalName == "ID").Value 解析为int(使用Parse()TryParse())。但由于某种原因,我不断收到以下错误:Input string was not in a correct format。这不会影响我(请求确实找到了与 ID 关联的名称,我可以返回 IEnumerable.ElementAt(0)),但如果我使用 IEnumerable.Count,则会弹出错误并使我的应用程序崩溃。
    • @Choub890 不确定您将 .Count 放在哪里。你能发布一些代码并告诉错误弹出的位置吗?
    【解决方案2】:

    问题中没有很清楚地说明(我认为预期输出的示例会澄清这一点),但假设您想要获取元素名称,其中ID 属性等于某个值并且目标元素可以是任何XML 文档中的级别深度,您可以像这样使用Descendants() 方法:

    IEnumerable<string> names =
           from el in xelement.Descendants()
           where (int)el.Attribute("ID") == "22"
           select (string)el.Name.LocalName;
    

    (int)el.Attribute("ID") 只需返回 0 - 而不是抛出异常 - 以防当前 el 中没有 ID 属性,因此您可以跳过检查 ID 属性的存在。

    【讨论】:

    • 这确实是我想要的,谢谢!如果我知道这些项目是&lt;Item_Types&gt; 节点的子项,我可以指定xelement.Descendants("Item_Types") 吗?出于某种原因,这样做总是返回 0 个元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    相关资源
    最近更新 更多