【问题标题】:Parsing Complex XML with C# LINQ使用 C# LINQ 解析复杂的 XML
【发布时间】:2016-10-20 14:53:51
【问题描述】:

我在 VS2012 的脚本转换中使用 c# 和 LINQ 来解析复杂的 xml soap 消息。我无法弄清楚如何遍历 xml 并在一行中获取我想要的所有元素。 xml如下。这只是返回的一部分。每项有48个区间,一般为5-6项。

<return>
<item>
    <interval>
        <intervalDate>
            <day>8</day>
            <month>7</month>
            <year>2016</year>
        </intervalDate>
        <intervalTime>
            <hours>0</hours>
            <militaryTime>true</militaryTime>
            <minutes>0</minutes>
            <seconds>0</seconds>
        </intervalTime>
        <laborType>forecasted</laborType>
        <volume>0.0</volume>
    </interval>
    <interval>
        <intervalDate>
            <day>8</day>
            <month>7</month>
            <year>2016</year>
        </intervalDate>
        <intervalTime>
            <hours>0</hours>
            <militaryTime>true</militaryTime>
            <minutes>30</minutes>
            <seconds>0</seconds>
        </intervalTime>
        <laborType>forecasted</laborType>
        <volume>0.0</volume>
    </interval>
    <jobCode>1</jobCode>
    <jobName>SERVER</jobName>
</item>
<item>
    <interval>
        <intervalDate>
            <day>8</day>
            <month>7</month>
            <year>2016</year>
        </intervalDate>
        <intervalTime>
            <hours>0</hours>
            <militaryTime>true</militaryTime>
            <minutes>0</minutes>
            <seconds>0</seconds>
        </intervalTime>
        <laborType>forecasted</laborType>
        <volume>0.0</volume>
    </interval>
    <interval>
        <intervalDate>
            <day>8</day>
            <month>7</month>
            <year>2016</year>
        </intervalDate>
        <intervalTime>
            <hours>0</hours>
            <militaryTime>true</militaryTime>
            <minutes>30</minutes>
            <seconds>0</seconds>
        </intervalTime>
        <laborType>forecasted</laborType>
        <volume>0.0</volume>
    </interval>
    <jobCode>50</jobCode>
    <jobName>Cashier</jobName>
</item>

我需要将数据输出到 5 列,datetime、laborType、laborVolume、laborJobCode 和 labourJobName。

laborDateTime|laborType|laborVolume|laborJobCode|laborJobName

2016-08-07 00:00:00.000|预测|0|1|服务器

2016-08-07 00:30:00.000|预测|0|1|服务器

2016-08-07 01:00:00.000|预测|0|1|服务器

2016-08-07 01:30:00.000|预测|0|1|服务器

我无法在网上找到任何示例来说明如何执行此操作。如果我遍历 Interval,我会返回预期的行数,但无法获取 JobCode 和 JobName。

    public override void CreateNewOutputRows()
{
    /*
      Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
      For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
    */

    String content = Variables.XMLString;

    XElement xdoc = XElement.Parse(content);

    var Interval = from interval in xdoc.Descendants("interval")
                   select new
                   {
                             laborIntervalDay = interval.Element("intervalDate").Element("day").Value,
                             laborIntervalMonth = interval.Element("intervalDate").Element("month").Value,
                             laborIntervalYear = interval.Element("intervalDate").Element("year").Value,
                             laborIntervalHour = interval.Element("intervalTime").Element("hours").Value,
                             laborIntervalMinutes = interval.Element("intervalTime").Element("minutes").Value,
                             laborIntervalSeconds = interval.Element("intervalTime").Element("seconds").Value,
                             laborIntervalMilitary = interval.Element("intervalTime").Element("militaryTime").Value,
                             laborType = interval.Element("laborType").Value,
                             laborVolume = interval.Element("volume").Value
                   };


            foreach (var q in Interval)
            {
                try
                {
                    DateTime dtBusinessDate = new DateTime(Convert.ToInt32(q.laborIntervalYear), Convert.ToInt32(q.laborIntervalMonth), Convert.ToInt32(q.laborIntervalDay), Convert.ToInt32(q.laborIntervalHour), Convert.ToInt32(q.laborIntervalMinutes), Convert.ToInt32(q.laborIntervalSeconds));
                    OUTLaborBuffer.AddRow();
                    OUTLaborBuffer.laborDateTime = dtBusinessDate;
                    OUTLaborBuffer.laborType = Convert.ToString(q.laborType);
                    OUTLaborBuffer.laborVolume = Convert.ToDouble(q.laborVolume);
                    //OUTLaborBuffer.laborJobCode = Convert.ToInt64(p.laborJobCode);
                    //OUTLaborBuffer.laborJobName = p.laborJobName;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error Message: " + ex.Message + " Message Detail: " + ex.StackTrace);
                }
            }

    }

我也尝试过遍历 Labor 和 Interval,但这不正确,因为它将当前 Labor 迭代的 JobCode/JobName 分配给所有间隔。如果有 5 个项目,那么我最终会得到预期行的 5 倍。

        var Interval = from interval in xdoc.Descendants("interval")
                   select new
                   {
                             laborIntervalDay = interval.Element("intervalDate").Element("day").Value,
                             laborIntervalMonth = interval.Element("intervalDate").Element("month").Value,
                             laborIntervalYear = interval.Element("intervalDate").Element("year").Value,
                             laborIntervalHour = interval.Element("intervalTime").Element("hours").Value,
                             laborIntervalMinutes = interval.Element("intervalTime").Element("minutes").Value,
                             laborIntervalSeconds = interval.Element("intervalTime").Element("seconds").Value,
                             laborIntervalMilitary = interval.Element("intervalTime").Element("militaryTime").Value,
                             laborType = interval.Element("laborType").Value,
                             laborVolume = interval.Element("volume").Value
                   };

    var Labor = from item in xdoc.Descendants("item")
                         select new
                         {
                             laborJobCode = item.Element("jobCode").Value,
                             laborJobName = item.Element("jobName").Value,
                         };

    foreach (var p in Labor)
    {
        // Save check information
        try
        {

            foreach (var q in Interval)
            {
                try
                {
                    DateTime dtBusinessDate = new DateTime(Convert.ToInt32(q.laborIntervalYear), Convert.ToInt32(q.laborIntervalMonth), Convert.ToInt32(q.laborIntervalDay), Convert.ToInt32(q.laborIntervalHour), Convert.ToInt32(q.laborIntervalMinutes), Convert.ToInt32(q.laborIntervalSeconds));
                    OUTLaborBuffer.AddRow();
                    OUTLaborBuffer.laborDateTime = dtBusinessDate;
                    OUTLaborBuffer.laborType = Convert.ToString(q.laborType);
                    OUTLaborBuffer.laborVolume = Convert.ToDouble(q.laborVolume);
                    OUTLaborBuffer.laborJobCode = Convert.ToInt64(p.laborJobCode);
                    OUTLaborBuffer.laborJobName = p.laborJobName;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error Message: " + ex.Message + " Message Detail: " + ex.StackTrace);
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error Message: " + ex.Message + " Message Detail: " + ex.StackTrace);
        }

    }


}

我在网上找到了一些示例,显示了正在解析的复杂 xml,如下所示:

        var Labor = from item in xdoc.Descendants("item")
                         select new
                         {
                             laborJobCode = item.Element("jobCode").Value,
                             laborJobName = item.Element("jobName").Value,
                             laborInterval = (from interval in xdoc.Descendants("interval")
                                              select new
                                              {
                                                laborIntervalDay = interval.Element("intervalDate").Element("day").Value,
                                                laborIntervalMonth = interval.Element("intervalDate").Element("month").Value,
                                                laborIntervalYear = interval.Element("intervalDate").Element("year").Value,
                                                laborIntervalHour = interval.Element("intervalTime").Element("hours").Value,
                                                laborIntervalMinutes = interval.Element("intervalTime").Element("minutes").Value,
                                                laborIntervalSeconds = interval.Element("intervalTime").Element("seconds").Value,
                                                laborIntervalMilitary = interval.Element("intervalTime").Element("militaryTime").Value,
                                                laborType = interval.Element("laborType").Value,
                                                laborVolume = interval.Element("volume").Value
                                              })
                         };

我用这种结构找到的例子是输出 ToList,我不知道如何以这种格式输出间隔的后代。你知道如何做到这一点吗?

【问题讨论】:

  • 在最后一次尝试中,尝试用 item.Descendants("interval") 替换 xdoc.Descendants("interval") 并添加 .ToArray() 以确保。

标签: c# xml linq ssis


【解决方案1】:

这样的事情应该可以解决问题:

    public dynamic OUTLaborBuffer;
    public dynamic Variables;

    public void CreateNewOutputRows()
    {
        String content = Variables.XMLString;
        XElement data = XElement.Parse(content);

        foreach (var item in data.XPathSelectElements("//item"))
        {
            var jobCode = item.Element("jobCode").Value;
            var jobName = item.Element("jobName").Value;

            foreach (var interval in item.XPathSelectElements("//interval"))
            {
                var laborIntervalDay = interval.Element("intervalDate").Element("day").Value;
                var laborIntervalMonth = interval.Element("intervalDate").Element("month").Value;
                var laborIntervalYear = interval.Element("intervalDate").Element("year").Value;
                var laborIntervalHour = interval.Element("intervalTime").Element("hours").Value;
                var laborIntervalMinutes = interval.Element("intervalTime").Element("minutes").Value;
                var laborIntervalSeconds = interval.Element("intervalTime").Element("seconds").Value;
                var laborIntervalMilitary = interval.Element("intervalTime").Element("militaryTime").Value;
                var laborType = interval.Element("laborType").Value;
                var laborVolume = interval.Element("volume").Value;

                DateTime dtBusinessDate = new DateTime(Convert.ToInt32(laborIntervalYear), Convert.ToInt32(laborIntervalMonth), Convert.ToInt32(q.laborIntervalDay), Convert.ToInt32(laborIntervalHour), Convert.ToInt32(laborIntervalMinutes), Convert.ToInt32(laborIntervalSeconds));
                OUTLaborBuffer.AddRow();
                OUTLaborBuffer.laborDateTime = dtBusinessDate;
                OUTLaborBuffer.laborType = Convert.ToString(laborType);
                OUTLaborBuffer.laborVolume = Convert.ToDouble(laborVolume);
                OUTLaborBuffer.laborJobCode = Convert.ToInt64(jobCode);
                OUTLaborBuffer.laborJobName = jobName;
            }
        }
    }

随意将 XPathSelectElements 改回 Descendants

【讨论】:

  • 感谢您的快速响应。您的代码对我来说很有意义,但是当我尝试代码时,我没有通过任务获得任何数据。没有错误,但没有数据。有什么想法吗?
  • 尝试添加断点以查看它是否到达 AddRow 并验证那里的数据。 (并且不要忘记删除动态对象>我只添加了那些,所以我不会在 VS 中遇到错误,因为我没有这些类型)
  • 我删除了动态对象,但仍然一无所获。我放了断点和消息框,但什么也没显示。任务立即完成并进入下一步。
【解决方案2】:

我能够通过使用 parent 来解决这个问题,以便在循环间隔时获取 JobCode 和 JobName。我基于这个例子:Linq on Complex XML

这是我最终得到的代码:

public override void CreateNewOutputRows()
{
    /*
      Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
      For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
    */

    String content = Variables.XMLString;

    XElement xdoc = XElement.Parse(content);

    var Interval = from interval in xdoc.Descendants("interval")
                   select new
                   {
                       laborJobCode = interval.Parent.Element("jobCode").Value,
                       laborJobName = interval.Parent.Element("jobName").Value,
                       laborIntervalDay = interval.Element("intervalDate").Element("day").Value,
                       laborIntervalMonth = interval.Element("intervalDate").Element("month").Value,
                       laborIntervalYear = interval.Element("intervalDate").Element("year").Value,
                       laborIntervalHour = interval.Element("intervalTime").Element("hours").Value,
                       laborIntervalMinutes = interval.Element("intervalTime").Element("minutes").Value,
                       laborIntervalSeconds = interval.Element("intervalTime").Element("seconds").Value,
                       laborIntervalMilitary = interval.Element("intervalTime").Element("militaryTime").Value,
                       laborType = interval.Element("laborType").Value,
                       laborVolume = interval.Element("volume").Value
                   };

    foreach (var q in Interval) 
        {
            try
                {
                    DateTime dtBusinessDate = new DateTime(Convert.ToInt32(q.laborIntervalYear), Convert.ToInt32(q.laborIntervalMonth), Convert.ToInt32(q.laborIntervalDay), Convert.ToInt32(q.laborIntervalHour), Convert.ToInt32(q.laborIntervalMinutes), Convert.ToInt32(q.laborIntervalSeconds));
                    OUTLaborBuffer.AddRow();
                    OUTLaborBuffer.laborDateTime = dtBusinessDate;
                    OUTLaborBuffer.laborType = Convert.ToString(q.laborType);
                    OUTLaborBuffer.laborVolume = Convert.ToDouble(q.laborVolume);
                    OUTLaborBuffer.laborJobCode = Convert.ToInt64(q.laborJobCode);
                    OUTLaborBuffer.laborJobName =  Convert.ToString(q.laborJobName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error Message: " + ex.Message + " Message Detail: " + ex.StackTrace);
                }
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    相关资源
    最近更新 更多