【问题标题】:Linq-to-xml group by elements that don't have child elementsLinq-to-xml 按没有子元素的元素分组
【发布时间】:2011-11-17 15:37:15
【问题描述】:

我想知道是否有人可以提供以下帮助:

我有一个这样的 xml 文档:

<div class="_cl">element description 1</div>
<div class="_cl">
    <anotherele>dtls</anotherele>
    <anotherele>moredtls</anotherele>
</div>
<div class="_cl">
    <anotherele>dtls</anotherele>
    <anotherele>moredtls</anotherele>
</div>
<div class="_cl">element description 2</div>
<div class="_cl">
    <anotherele>dtls</anotherele>
    <anotherele>moredtls</anotherele>
</div>
<div class="_cl">
    <anotherele>dtls</anotherele>
    <anotherele>moredtls</anotherele>
</div>

我想知道 linq 中是否有任何方法可以按没有子元素的元素对其进行分组。基本上,尝试像这样构造文档:

<div class="_cl">element description 1
   <div class="_cl">
       <anotherele>dtls</anotherele>
       <anotherele>moredtls</anotherele>
   </div>
   <div class="_cl">
       <anotherele>dtls</anotherele>
       <anotherele>moredtls</anotherele>
   </div>
</div>
<div class="_cl">element description 2
   <div class="_cl">
       <anotherele>dtls</anotherele>
       <anotherele>moredtls</anotherele>
   </div>
   <div class="_cl">
       <anotherele>dtls</anotherele>
       <anotherele>moredtls</anotherele>
   </div>
</div>

我的第一次可悲的尝试是这样的:

var n = from a in doc.Descendants()
                where a.Name.LocalName == "div" && (string)a.Attribute("class") == "_cl"
                group a by a.Value.Length<50 into g 
                select new { k = g.Key, p = g.Count() };

希望这是有道理的,并提前感谢。

学习

【问题讨论】:

  • 我真的不明白你想做什么......你不能按条件分组 - 你可以按字段分组......没有子元素是一个条件,你可以过滤由它,但不是组。
  • 如果你说的是真的,那就不可能了。您还有其他解决方案来塑造 xml 吗?
  • 我的意思是,您的请求不合逻辑...请更正确地解释您要做什么。示例输出可能会很好。

标签: c# .net linq linq-to-xml


【解决方案1】:

这里是一个例子,假设输入是

<body>
<div class="_cl">element description 1</div>
<div class="_cl">
  <anotherele>dtls</anotherele>
  <anotherele>moredtls</anotherele>
</div>
<div class="_cl">
  <anotherele>dtls</anotherele>
  <anotherele>moredtls</anotherele>
</div>
<div class="_cl">element description 2</div>
<div class="_cl">
  <anotherele>dtls</anotherele>
  <anotherele>moredtls</anotherele>
</div>
<div class="_cl">
  <anotherele>dtls</anotherele>
  <anotherele>moredtls</anotherele>
</div>
</body>

然后是代码

    XDocument input = XDocument.Load("input.xml");

    XDocument output = new XDocument(
        new XElement(input.Root.Name,
            from el in input.Root.Elements()
            where el.Elements().Any()
            group el by el.NodesBeforeSelf().OfType<XElement>().LastOrDefault(e => !e.Elements().Any()) into g
            select new XElement(g.Key.Name,
                g.Key.Attributes(),
                g.Key.Nodes(),
                g)
            ));

    output.Save(Console.Out);

输出

<body>
  <div class="_cl">element description 1<div class="_cl"><anotherele>dtls</anoth
erele><anotherele>moredtls</anotherele></div><div class="_cl"><anotherele>dtls</anotherele><anotherele>moredtls</anotherele></div></div>
  <div class="_cl">element description 2<div class="_cl"><anotherele>dtls</anoth
erele><anotherele>moredtls</anotherele></div><div class="_cl"><anotherele>dtls</anotherele><anotherele>moredtls</anotherele></div></div>
</body>

除了缩进之外,这就是您想要的。至于缩进,您可以通过使用XDocument.Load("input.xml", LoadOptions.PreserveWhitespace) 加载输入来更接近您想要的结果。

有关此分组方法的更多信息,请参阅http://msmvps.com/blogs/martin_honnen/archive/2009/11/27/grouping-with-linq-to-xml.aspx

【讨论】:

    【解决方案2】:

    斯瓦罗格是对的;您尝试做的事情无法通过分组来实现。您需要一些比 Linq 关键字中给出的更高级的 Linq 表达式。

    试试这个:

    var n = doc.Elements().Where(div=>!div.Elements().Any()).
            Select(div=>{
                div.Add(
                    div.ElementsAfterSelf().TakeWhile(x=>x.Elements().Any())
                ); 
                return div;
            }); 
    

    【讨论】:

      【解决方案3】:

      感谢您的意见,但似乎没有一个解决方案能完全解决问题。我想我要做的就是遍历元素并手动解析它。我只是认为一个好的 linq 单线会更好。

      干杯

      学习

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多