linq查询解析给定的复杂xml

时间:2014-03-26 03:54:15

标签: c# xml linq xml-parsing

我有一个类似于下面的xml,其中root为rail

        <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一次解析一个孩子及其属性,但我想解析所有的孩子及其元素。 比如说trainNumer =“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查询中获取所有这些?如何? 如果不是那么在这种情况下哪种方法是正确的..

1 个答案:

答案 0 :(得分:1)

以下是我的建议:

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