【问题标题】:c# LINQ to filter XML, keep tree hierarchyc# LINQ 过滤 XML,保持树的层次结构
【发布时间】:2017-04-15 15:20:52
【问题描述】:

我已经像这样过滤了我的数据 IEnumerable

   xDOCfiltered = xDOC
        .Where(k => 
            (
                ( k.Attribute("Object_Heading").Value.Trim() == "Author" && k.Parent.Attribute("Milestones").Value.Contains(milestone) )
                //
                || k.Attribute("Milestones").Value.Contains(milestone)
            ) 

            && filterUID.IsMatch(k.Attribute("Unique_ID").Value.Trim())
            && GetHierarchy(k).First() == "Code"
            )
        ;

现在我在使用的时候才发现

foreach (XElement xobj in xGDMfiltered)
{
...
...
XNode previousNode = xobj.PreviousNode;
...
...

}

我的 PREV 节点是指原始的 xDOC 结构,没有过滤一个 :( 我不清楚,LINQ返回的xDOCfiltered只是一个普通的列表,所有层次信息都丢失了?

这似乎是并且在某种程度上是合乎逻辑的,linq 将返回一个集合。

我按如下方式加载我的结构

            x= XDocument.Load(myXml);

            xDOC = x.Element("root").Descendants("record");

我可以以某种方式过滤并仍然保留(重建)层次结构吗? 类似于删除所有按 LINQ 表达式过滤的节点?

非常感谢您,

附言。 我想到的第一件事是对过滤列表进行 foreach 并从 x 文档中删除该节点,但有更优雅的解决方案吗?

这需要几分钟,原始未经过滤的文档有 >18.000 个节点!

【问题讨论】:

  • 您的问题不清楚 - 您首先要达到的目标并不明显。如果您澄清您的问题,最好包括minimal reproducible example,您可能会发现有一种比您发布的答案更简单的方法。
  • @Jon,我尽力了。我不能在这里发布 18k 条 XML 记录。这个想法是 XElements 组不会像在 XML 文档中那样保持原始的嵌套层次结构。这是在使用 LINQ 过滤之后。所以访问 node.Previous 属性是没有意义的。
  • 我没有要求 18K 记录。我要了minimal reproducible example。您所要展示的只是一些有代表性的东西,我们可以用它来理解您的问题是什么。请阅读codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question

标签: xml


【解决方案1】:

如果有人需要这个,我首先否定所有子句,然后立即删除所有不匹配的节点。与 foreach remove 相比,这非常快。

            x.Element("root").Descendants("record") // delete if
                .Where(k => 
                    !( // NEGATE so keep this kind of objects

                        // contains desired milestone
                        k.Attribute("Milestones").Value.Contains(milestone)

                        || // or

                        (k.Attribute("Object_Heading").Value.Trim() == "Author" && k.Parent.Attribute("Milestones").Value.Contains(milestone))
                    ) 

                    // or if UID is not in this format
                    || !filterUID.IsMatch(k.Attribute("Unique_ID").Value.Trim()) // and this format for UID

                    // or if first parent (except root) is not a Code  
                    || GetHierarchy(k).First() != "Code"

                    ).Remove()
                ;

                xDOCfiltered =
                    x.Element("root").Descendants("record");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    相关资源
    最近更新 更多