Linq查询解析给定的复杂xml
本文关键字:复杂 xml 查询 Linq | 更新日期: 2023-09-27 17:53:34
我有一个像下面这样的xml,根作为轨道
<rail>
<timetable>
<trainParts>
<trainPart id="tp_1" name="1" timetablePeriodRef="ttp_2012_13" categoryRef="cat_Commuter" processStatus="planned" trainNumber="1">
<operatingPeriodRef ref="Daily" />
<ocpsTT>
<ocpTT ocpType="begin" ocpRef="ocp_SWH">
<sectionTT trackInfo="SWH-DM" />
</ocpTT>
<ocpTT ocpType="stop" ocpRef="ocp_SE">
<times arrival="16:16:00" departure="16:18:00" scope="scheduled" />
<sectionTT trackInfo="SE-DM" />
</ocpTT>
.
.
.
so on
</ocpsTT>
</trainPart>
</trainParts>
</timetable>
</rail>
现在就像这样,有许多车次,我必须一次解析它们的详细信息。我可以解析一个孩子和它的属性在一次使用linq,但我想解析所有的孩子和它的元素。比如for trainnumber ="1"我需要得到
categoryRef
processStatus
operatingPeriodRef
ocpType
ocpRef
trackInfo
arrival
departure
注意:在某些情况下,包含出发到达的时间标签不存在
我试着这样写代码:
public void trainDetails(string trainNumber)
{
var xdoc = XDocument.Load("Rail.xml");
XNamespace ad = "http://www.rail.org/schemas/2009";
var train = (from t in xdoc.Root.Elements(ad + "timetable")
let d = t.Element(ad + "trainParts").Element("trainPart")
where (string)t.Attribute("number") == trainNumber
select new
{
operatingPeriod=(from s1 in d.Elements(ad+"operatingPeriodRef")
operatingref=(string)s1.Attribute("ref")
}).ToList()
}
select new
{
trainOcpsTT= (from s2 in d.Elements(ad + "ocpsTT").Elements(ad+"ocpTT")
select new
{
ocpType=(string)s2.Attribute("ocpType"),
ocpRef=(string)s2.Attribute("ocpRef")
}).ToList()
}).FirstOrDefault();
}
}
我无法正确地构建查询。是否有可能得到所有这些在一个xml linq查询本身?如何?如果不是,那么在这种情况下,哪种方法是正确的……
我的建议是:
public class TrainInfo
{
public string categoryRef { get; set; }
public int trainNumber { get; set; }
public string processStatus { get; set; }
public string operatingPeriodRef { get; set; }
public List<ocpsTTs> ocpsTT { get; set; }
}
public struct ocpsTTs
{
public string ocpType;
public string ocpRef;
public string arrival;
public string departure;
public string scope;
public string trackInfo;
}
class Program
{
static void Main(string[] args)
{
TrainInfo ti = ProcessXml(@"XMLFile1.xml", 1);
}
static TrainInfo ProcessXml(string xmlfile, int trainnumber)
{
TrainInfo retVal;
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlfile);
XNamespace xns = "http://www.rail.org/schemas/2009";
XDocument xdoc = System.Xml.Linq.XDocument.Parse(xmlDoc.InnerXml);
retVal =
(from c
in xdoc.Root.Elements(xns + "timetable").Elements(xns + "trainParts").Elements(xns + "trainPart")
where c.Attribute("trainNumber").Value.Equals(trainnumber.ToString())
select new TrainInfo
{
categoryRef = c.Attribute("categoryRef").Value,
trainNumber = Int32.Parse(c.Attribute("trainNumber").Value),
processStatus = c.Attribute("processStatus").Value,
operatingPeriodRef = c.Element(xns + "operatingPeriodRef").Attribute("ref").Value,
ocpsTT = (from tt in c.Elements(xns + "ocpsTT").Descendants(xns + "ocpTT")
let timeinfo = tt.Elements(xns + "times").Any()
select new ocpsTTs
{
ocpType = tt.Attribute("ocpType").Value,
ocpRef = tt.Attribute("ocpRef").Value,
arrival = timeinfo ? tt.Element(xns + "times").Attribute("arrival").Value : string.Empty,
departure = timeinfo ? tt.Element(xns + "times").Attribute("departure").Value : string.Empty,
scope = timeinfo ? tt.Element(xns + "times").Attribute("scope").Value : string.Empty,
trackInfo = tt.Element(xns + "sectionTT").Attribute("trackInfo").Value,
}).ToList()
}).FirstOrDefault();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
retVal = null;
}
return retVal;
}
}