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
    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 に答える
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 に答える