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查询本身?如何?如果不是,那么在这种情况下,哪种方法是正确的……

Linq查询解析给定的复杂xml

我的建议是:

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;
    }
}