【问题标题】:Read XML data and sort into list based on conditions读取 XML 数据并根据条件排序到列表中
【发布时间】:2018-03-17 06:56:12
【问题描述】:

您好,这是关于我正在尝试完成的一个小项目的第二个问题,第一个问题是基于将两个文本文件中的一些数据匹配到一对列表中进行比较。现在我想对我通过 HTTP 从一个 restful API 收到的一些数据进行排序,从第一个问题中的一个列表中获取列表。

这是文本文件的片段

C1903:009030           COMMERCIAL BREAK - 30 SE   0030COM
C1904:009040           COMMERCIAL BREAK - 40 SE   0040COM
C1918:009240           COMMERCIAL BREAK - 2 MIN   0240CO

这里是 XML 数据的片段

<RCSZettaAPIResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://rcsworks.com">
    <ResponseType>Success</ResponseType>
    <SyncCounter>1285121525</SyncCounter>
    <DataObject i:type="StationScheduleLog">
        <Date>2017-10-04T00:00:00</Date>
        <HourGroupCollection>
            <HourGroup>
                <Hour>19</Hour>
                <LogEventCollection>
                    <LogEvent>
                        <Chain>Segue</Chain>
                        <DisplayText>ExactTimeMarker - Reset : 00:00:00</DisplayText>
                        <ExactTimeMarkerEvent>
                            <Type>Reset</Type>
                        </ExactTimeMarkerEvent>
                        <StatusCode>Ready</StatusCode>
                        <Type>ExactTimeMarker</Type>
                        <UUID>d67afec1-59a3-e711-80ef-308d99b21a00</UUID>
                        <VerifyID></VerifyID>
                    </LogEvent>
                    <LogEvent>
                        <Chain>Stop</Chain>
                        <CommentEvent>
                            <Duration>PT3M</Duration>
                            <Text>Note: 3 Min Eagle News Bulletin</Text>
                        </CommentEvent>
                        <DisplayText>Comment - Note: 3 Min  News Bulletin</DisplayText>
                        <StatusCode>Ready</StatusCode>
                        <Type>Comment</Type>
                        <UUID>d77afec1-59a3-e711-80ef-308d99b21a00</UUID>
                        <VerifyID></VerifyID>
                    </LogEvent>
                    <LogEvent>
                        <Chain>Segue</Chain>
                        <DisplayText>ExactTimeMarker - Hit : 00:03:00</DisplayText>
                        <ExactTimeMarkerEvent>
                            <Time>PT3M</Time>
                            <Type>Hit</Type>
                        </ExactTimeMarkerEvent>
                        <StatusCode>Ready</StatusCode>
                        <Type>ExactTimeMarker</Type>
                        <UUID>d87afec1-59a3-e711-80ef-308d99b21a00</UUID>
                        <VerifyID></VerifyID>
                    </LogEvent>
                    <LogEvent>
                        <Chain>Segue</Chain>
                        <DisplayText>Spot Block</DisplayText>
                        <SpotBlockEvent>
                            <LogEventCollection>
                                <LogEvent>
                                    <AssetEvent>
                                        <EffectiveTransitions>
                                            <Duration>PT30.41S</Duration>
                                            <Runtime>PT30S</Runtime>
                                            <Segue>PT30S</Segue>
                                            <TrimIn>PT0S</TrimIn>
                                            <TrimOut>PT30.41S</TrimOut>
                                        </EffectiveTransitions>
                                        <Type>Spot</Type>
                                        <UUID>e2a39f0b-647b-4308-b85d-3f38affd2251</UUID>
                                    </AssetEvent>
                                    <Chain>Segue</Chain>
                                    <DisplayText>COMMERCIAL BREAK - 30 SEC ( 00:30.4 )</DisplayText>
                                    <EditCode>FlatFileInsert</EditCode>
                                    <StatusCode>Ready</StatusCode>
                                    <Type>Asset</Type>
                                    <UUID>ff4d423b-c79b-440c-bb98-e938871279dc</UUID>
                                    <VerifyID></VerifyID>
                                </LogEvent>
                            </LogEventCollection>
                            <OverrideSplitMode>Monitor</OverrideSplitMode>
                        </SpotBlockEvent>
                        <StatusCode>Ready</StatusCode>
                        <Type>SpotBlock</Type>
                        <UUID>d97afec1-59a3-e711-80ef-308d99b21a00</UUID>
                        <VerifyID></VerifyID>
                    </LogEvent>

我需要检查日期标签&lt;Date&gt;2017-10-04T00:00:00&lt;/Date&gt;,如果日期正确,请检查日志文件C1903(即下午7.03)中的第一个中断,它们与小时标签&lt;Hour&gt;19&lt;/Hour&gt;匹配,并且小步舞曲标记为

处的确切时间标记
                        <ExactTimeMarkerEvent>
                            <Time>PT3M</Time>
                            <Type>Hit</Type>
                        </ExactTimeMarkerEvent>

由精确时间标签中的PT3M数据表示,然后匹配0030COM(30秒)的中断时间长度匹配&lt;Type&gt;SpotBlock&lt;/Type&gt;元素内的xml&lt;Runtime&gt;PT30S&lt;/Runtime&gt;中的中断时间。

如果这些不匹配,那么我需要通知用户不匹配。

我远远超出了我的技能范围,但我喜欢挑战。我只是不知道如何去做,所以任何帮助指导将不胜感激

谢谢

西蒙

编辑使用来自 jdweng 的编辑添加到此

private void btnGetLog_Click(object sender, EventArgs e)
        {
            // client.Authenticator = new HttpBasicAuthenticator(username, password);
            var client = new RestClient("http://" + tbZettaAPIServer.Text + ":3139");

            var request = new RestRequest("1.0/{id}/{stuuid}/{date}?hourFrom={startHour}&hourTo={endHour}", Method.GET);
            //request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
            // replaces matching token in request.Resource
            request.AddUrlSegment("id", "StationScheduleLog"); // replaces matching token in request.Resource
            request.AddUrlSegment("stuuid", tbStationUUID.Text);
            request.AddUrlSegment("date", xmlDate);
            request.AddUrlSegment("startHour", "19");
            request.AddUrlSegment("endHour", "20");

            // adds to POST or URL querystring based on Method
            request.AddHeader("APIKEY", tbZettaAPIKey.Text);
            request.AddHeader("Accept", "application/xml");
            request.AddHeader("Content-Type", "application/xml");
            request.AddHeader("Authorization", "Basic " + zettaUsernameBase64);
            //request.AddHeader("Authorization", "Basic c3VwZXJ2aXNvcjo=");

            // replaces matching token in request.Resource
            //request.AddUrlSegment("id", "123"); 

            // easy async support
            client.ExecuteAsync(request, response => 
            {
                //tbXMLLog.Text = (response.Content);
                xmlResponce = (response.Content);

            });
            if (xmlResponce != null)
            {
                //XDocument zettaXML = XDocument.Parse(xmlResponce);
                XDocument zettaXML = XDocument.Parse(xmlResponce);
                XElement root = zettaXML.Root;
                XNamespace ns = root.GetDefaultNamespace();

                var results = root.Descendants(ns + "DataObject").Select(x => new {
                    date = (DateTime)x.Element(ns + "Date"),
                    hour = (int)x.Descendants(ns + "Hour").FirstOrDefault(),
                    time = (string)x.Descendants(ns + "Time").FirstOrDefault(),
                    runtime = (string)x.Descendants(ns + "Runtime").FirstOrDefault(),
                    displayText = x.Descendants(ns + "LogEvent").Where(y => (y.Element(ns + "AssetEvent") != null) && (y.Descendants(ns + "Runtime").Any())).Select(y => (string)y.Descendants(ns + "DisplayText").FirstOrDefault()).FirstOrDefault()
                }).ToList();


            }
        }

【问题讨论】:

  • 你用过XDocument还是XPath?这些将是您用来查询 XML 数据并在节点上执行所需的任何排序的主要对象
  • 我已经使用XDocument 将日期存储在zettaXML 中,就像这样XDocument zettaXML = XDocument.Parse(xmlResponce);

标签: c# xml list sorting


【解决方案1】:

我使用 xml linq 从以下代码中的文件中获取了四个标签(加上显示文本):

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

namespace ConsoleApplication1
{
    class Program
    {
        const string URL = "https://pastebin.com/raw/Ch1BeS0k";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(URL);
            XElement root = doc.Root;
            XNamespace ns = root.GetDefaultNamespace();

            var results = root.Descendants(ns + "DataObject").Select(x => new
            {
                date = (DateTime)x.Element(ns + "Date"),
                hour = (int)x.Descendants(ns + "Hour").FirstOrDefault(),
                time = (string)x.Descendants(ns + "Time").FirstOrDefault(),
                runtime = (string)x.Descendants(ns + "Runtime").FirstOrDefault(),
                displayText = x.Descendants(ns + "LogEvent").Where(y => (y.Element(ns + "AssetEvent") != null) && (y.Descendants(ns + "Runtime").Any())).Select(y => (string)y.Descendants(ns + "DisplayText").FirstOrDefault()).FirstOrDefault()
            }).FirstOrDefault();
        }
    }
}

下面的代码获取所有的日志事件


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Globalization;

namespace ConsoleApplication1
{
    class Program
    {
        const string URL = "https://pastebin.com/raw/Ch1BeS0k";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(URL);
            XElement root = doc.Root;
            XNamespace ns = root.GetDefaultNamespace();

            var results = root.Descendants(ns + "DataObject").Select(dataObject => new
            {
                hourGroups = dataObject.Descendants(ns + "HourGroup").Select(hourGroup => new
                {
                    logEvents = hourGroup.Descendants(ns + "LogEvent").Select(logEvent => new
                    {
                        date = (DateTime)dataObject.Element(ns + "Date"),
                        hour = (int)hourGroup.Element(ns + "Hour"),
                        time = (string)logEvent.Descendants(ns + "Time").FirstOrDefault(),
                        runtime = (string)logEvent.Descendants(ns + "Runtime").FirstOrDefault(),
                        displayText = (logEvent.Element(ns + "AssetEvent") != null) && (logEvent.Descendants(ns + "Runtime").Any()) ? (string)logEvent.Descendants(ns + "DisplayText").FirstOrDefault() : string.Empty
                    }).ToList()
                }).SelectMany(x => x.logEvents)
            }).SelectMany(x => x.hourGroups).ToList();

            int minute = 0;
            string minutePattern = @"PT(?'minutes'\d+)M";
            string timespanPattern = @"\(\s*(?'timespan'[^\s]+)\s+\)";
            foreach (var result in results)
            {
                if (result.time != null)
                {
                    minute = int.Parse(Regex.Match(result.time, minutePattern).Groups["minutes"].Value);
                }
                if (result.displayText.Contains("COMMERCIAL BREAK"))
                {
                    string timeSpanStr = Regex.Match(result.displayText, timespanPattern).Groups["timespan"].Value;
                    DateTime timeSpan = DateTime.ParseExact(timeSpanStr, "mm:ss.f", CultureInfo.InvariantCulture);
                    Console.WriteLine("C{0}{1}:0{2}{3}       {4}", result.hour.ToString("00"), minute.ToString("00"), (result.hour % 12).ToString("00"),timeSpan.ToString("mmss"), result.displayText);
                }
            }
            Console.ReadLine();
        }
    }
}

样本输出

C1903:0070030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C1904:0070030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C1918:0070250       COMMERCIAL BREAK - 2 MIN 50 SEC ( 02:50.0 )
C1927:0070230       COMMERCIAL BREAK - 2 MIN 30 SEC ( 02:30.1 )
C1935:0070030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C1946:0070030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C1947:0070240       COMMERCIAL BREAK - 2 MIN 40 SEC ( 02:40.1 )
C1957:0070250       COMMERCIAL BREAK - 2 MIN 50 SEC ( 02:50.0 )
C2003:0080030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C2004:0080030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C2018:0080240       COMMERCIAL BREAK - 2 MIN 40 SEC ( 02:40.1 )
C2027:0080230       COMMERCIAL BREAK - 2 MIN 30 SEC ( 02:30.1 )
C2030:0080030       COMMERCIAL BREAK - 30 SEC ( 00:30.4 )
C2047:0080220       COMMERCIAL BREAK - 2 MIN 20 SEC ( 02:20.1 )
C2057:0080220       COMMERCIAL BREAK - 2 MIN 20 SEC ( 02:20.1 )

【讨论】:

  • 嗨,jdweng,我已经在按下按钮进行测试时实现了它,它只检查第一行所以我想我需要循环它?我怎么知道它要进入哪个列表,我不是一个训练有素的编码员,只是为了好玩和零工,让我的工作生活更轻松。我无法粘贴在代码下方,因此将添加到原始问题中。谢谢西蒙
  • results 是一个列表,因此您需要放入 foreach(var dataObject in results){your code here}。然后将每个结果与您的文本文件进行比较。
  • 那里似乎只有一个结果,所以没有什么可以循环的
  • 我不确定,因为您说您发布了 xml 的片段。编写了 XML,以防万一您有多个它仍然可以工作。您知道如何获取结果并根据需要重新格式化吗?
  • 也许,我有点想通了,有点!!我想如果没有问题要解决,我就学不会一门语言,所以我一直在糊里糊涂地使用堆栈和谷歌!!!,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多