XML LINQ帮助

时间:2014-05-28 13:15:08

标签: xml linq

我目前正在研究XML并在C#中使用它并将其与LINQ一起使用。

我有以下

我的XML文件

<RECSTEPS>
<RECSTEPS1>
    <STEP>Step 1 - prepare</STEP>
    <STEP>Step 2 - cut</STEP>
</RECSTEPS1>
<RECSTEPS2>
    <STEP>Step 1 - prepare</STEP>
    <STEP>Step 2 - cut</STEP>
    <STEP>Step 3 - Weld</STEP>
</RECSTEPS2>
<RECSTEPS3>
    <STEP>Step 1 - prepare</STEP>
    <STEP>Step 2 - cut</STEP>
</RECSTEPS3>
</RECSTEPS>

我使用的代码如下:

string strFileName=@"\\wlfp02\home\CS4\nsavidge\Work\XML\test2.xml";

        XDocument xd =  XDocument.Load(strFileName);

        var t = xd.Descendants("RECSTEPS2");

        foreach (XElement xe in t.Elements())
        {
            Console.WriteLine(xe.Value);
        }

这很好,但是,我正在尝试使用LINQ来做同样的事情。我得到了相同的数量,但是无法接受我的输出,即可数内的数字。我看过手表,但不能确定。

var t2 = xd.Root.Elements().Select(o => o.Element("RECSTEPS2"));

由于

2 个答案:

答案 0 :(得分:0)

你的代码错了。它应该是:

var t2 = xd.Descendants("RECSTEPS2")
            .SelectMany(e => e.Elements());

在您的查询中,您将根节点的每个元素投影到RECSTEPS2元素的值。换句话说,您的查询将返回与根节点下的元素数量一样多的元素RECSTEPS2的副本。

你在想的是过滤,即使用Where运算符,如下所示:

var t2 = xd.Root.Elements()
            .Where(e => e.Name == "RECSTEPS2");

但是上面会给你一个IEnumerable<XElement>,它符合元素RECSTEPS2的标准(尽管只有一个)。 换句话说,使用上面的代码迭代RECSTEPS2的子元素,你需要一个双循环:

foreach(var parent in t2)
    foreach(var child in parent)
        Console.WriteLine(child.Value);

使用SelectMany的好处是它可以展平元素的层次结构,只给出RECSTEPS2节点的子元素,这样您的完整代码就会如下所示:

var t2 = xd.Descendants("RECSTEPS2")
            .SelectMany(e => e.Elements());
foreach(var xe in t2)
    Console.WriteLine(xe.Value);
// Will print
// Step 1 - prepare etc

答案 1 :(得分:0)

首先,帮自己一个忙,得到Linqpad。它允许您使用Linq查询并立即获得您的查询正在进行的视觉反馈。

将代码直接翻译为Linq是:

IEnumerable<string> stepTwoSteps = xd.Root
                                     .Descendants("RECSTEPS2")
                                     .Elements()
                                     .Select (rs2 => rs2.Value);

foreach(string stepValue in stepTwoSteps)
{
    Console.WriteLine(stepValue);
}

有些事情需要考虑:

  1. RECSTEPS2总是直接位于根目录下吗?如果是这样,您最好使用Elements("RECSTEPS2")代替Descendants("RECSTEPS2"),因为后者搜索XML结构的所有深度,前者仅在其使用的节点下立即查看
  2. 是否有可能存在多个&#34; RECSTEPS2&#34;元件?知道你的查询将同时选择任何&#34; STEP&#34;元素,可能会造成重复。
  3. 我猜你正在寻找更多的东西:

    var stepTwoSteps = xd.Root
                         .Elements("RECSTEPS2")
                         .Elements("STEP")
                         .Select (step => step.Value)
    
    foreach(string stepValue in stepTwoSteps)
    {
        Console.WriteLine(stepValue);
    }