用c# LINQ解析复杂的XML
本文关键字:复杂 XML LINQ | 更新日期: 2023-09-27 18:14:14
我在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和laborJobName。
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,我不知道如何以这种格式输出interval的后代。你知道该怎么做吗?
类似这样的代码应该可以达到这个效果:
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
我可以通过在循环间隔时使用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);
}
}
}