0

我得到了这个 XML 文件:

<Msg UserText="start 0">
</Msg>
<Msg UserText="A">
</Msg>
<Msg UserText="A">
</Msg>
<Msg UserText="start 1">
</Msg>
<Msg UserText="A">
</Msg>
<Msg UserText="start 2">
</Msg>
<Msg UserText="A">
</Msg>
<Msg UserText="A">
</Msg>
<Msg UserText="A">
</Msg>

我需要计算每个“开始 x”之间有多少个“A”

即对于上面我会输出:

start 0 : 2 
start 1 : 1 
start 2 : 3

我应该如何在 C# 中解决这个问题?我有几个方向,但我确信那里有更简单的方向(例如使用 linq)

4

4 回答 4

2

这是一个分组示例:

XDocument doc = XDocument.Load("../../XMLFile1.xml");

var groups = from msg in doc.Root.Elements("Msg")
             where !((string)msg.Attribute("UserText")).StartsWith("start")
             group msg by 
             msg.ElementsBeforeSelf("Msg").Where(m => 
                 ((string)m.Attribute("UserText")).StartsWith("start")).Last();

foreach (var group in groups)
{
    Console.WriteLine("Group starting with {0} has {1} member(s).", 
        group.Key.Attribute("UserText"), group.Count());
}

使用 XML 输入示例 XMLFile1.xml

<Root>
  <Msg UserText="start 0">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="start 1">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="start 2">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="A">
  </Msg>
</Root>

我得到输出

Group starting with UserText="start 0" has 2 member(s).
Group starting with UserText="start 1" has 1 member(s).
Group starting with UserText="start 2" has 3 member(s).
于 2012-07-01T18:05:13.243 回答
1

这应该为你做。

using System.Collections.Generic;
using System.Xml.Linq;

namespace TraverseXMLNodes
{
    public class Class1
    {
        public static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(@"C:\Udvikling\StackOverflow\TraverseXMLNodesSln\TraverseXMLNodes\XMLFile1.xml");
            var msgs = doc.Element("root").Elements("Msg");

            List<int> numbers = new List<int>();
            List<string> numbersStr = new List<string>();
            int count = 0;
            foreach (var xElement in msgs)
            {
                string value = xElement.Attribute("UserText").Value;
                numbersStr.Add(value);
                if (value.Contains("start"))
                {
                    numbers.Add(count);
                    count = 0;
                }
                else
                {
                    count++;
                }
            }
            numbers.Add(count);
        }
    }
}

我的 XML 文件:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <Msg UserText="start 0">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="start 1">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="start 2">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="A">
  </Msg>
  <Msg UserText="A">
  </Msg>
</root>
于 2012-07-01T17:58:56.680 回答
1
    static void Main(string[] args)
    {
         const string xml = @"<SomeRootTag>
            <Msg UserText='start 0'>
            </Msg>
            <Msg UserText='A'>
            </Msg>
            <Msg UserText='A'>
            </Msg>
            <Msg UserText='start 1'>
            </Msg>
            <Msg UserText='A'>
            </Msg>
            <Msg UserText='start 2'>
            </Msg>
            <Msg UserText='A'>
            </Msg>
            <Msg UserText='A'>
            </Msg>
            <Msg UserText='A'>
            </Msg>
        </SomeRootTag>";

        var xDoc = XDocument.Load(new StringReader(xml));
        var msgs = xDoc.Root.Elements().Where(el => el.Name == "Msg").Select(el => el.Attribute("UserText").Value);
        var results = GetCounts(msgs);



        foreach (var keyValue in results)
        {
            Console.WriteLine("{0}:{1}", keyValue.Item1, keyValue.Item2);
        }

        Console.ReadKey();
    }

    private static IEnumerable<Tuple<string,int>> GetCounts(IEnumerable<string> msgs)
    {
        string last = null;
        int count = 0;
        foreach (var msg in msgs)
        {
            if (msg.StartsWith("start"))
            {
                if (last != null)
                {
                    yield return new Tuple<string, int>(last, count);
                }
                count = 0;
                last = msg;
            }
            else
            {
                count++;
            }
        }
        yield return new Tuple<string, int>(last, count);
    }  
于 2012-07-01T18:12:13.723 回答
1

利用该ElementsAfterSelf()方法获得以下兄弟姐妹。然后从那里很容易:

var root = XElement.Parse(xmlStr);
var query =
    from msg in root.Elements("Msg")
    let message = (string)msg.Attribute("UserText")
    where message.StartsWith("start")
    select new
    {
        Message = message,
        FollowingAs = msg.ElementsAfterSelf("Msg")
            .TakeWhile(e => (string)e.Attribute("UserText") == "A")
            .Count(),
    };
于 2012-07-01T18:17:03.070 回答