Linq-to-xml组由没有子元素的元素组成

时间:2011-11-17 15:37:15

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

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

我有一个像这样的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() };

希望这是有意义的,并提前感谢。

斯图

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

Svarog是对的;你想要做的事情不能通过分组来实现。你需要一些比Linq关键字更高级的Linq表达式。

试试这个:

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

答案 2 :(得分:0)

感谢您的投入,但没有一个解决方案似乎完全削减了它。我想我要做的只是遍历元素并手动解析它。我只是觉得一个漂亮的linq单线会更好。

干杯

斯图