代码之家  ›  专栏  ›  技术社区  ›  Sam

Linq到XML-获取属性和元素

  •  1
  • Sam  · 技术社区  · 4 年前

    给定这个XML,我如何获得每个outageEvent的数据,包括属性和元素?

    最后,我需要将这些数据移动到数据库中,但这是第一步。

    所需的结束格式是具有属性的每个outageEvent的“行” ObjectID 然后是outageEvent中的元素。

    outageEvent
    -------------
    ObjectID
    Comment
    objectName
    ...etc.
    

    此时不需要获取outageEvent的孙辈,如ExtensionList子代。

    到目前为止,我正在使用Linq-to-XML进行查询。我可以查询并获取对象ID。另外,我可以查询得到所有的元素。试图把两者结合起来给我带来了麻烦。有一段时间没有做任何C#,所以这是99%的问题。

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Header>
        </soap:Header>
        <soap:Body>
            <OutageEventChangedNotification xmlns="http://www.multispeak.org/Version_4.1_Release">
                <oEvents>
                    <outageEvent objectID="2021-10-16-0002">
                        <comments>Test outage 2</comments>
                        <extensionsList>
                            <extensionsItem>
                                <extName>primaryCrew</extName>
                                <extValue>Primary Crew Name</extValue>
                                <extType>string</extType>
                            </extensionsItem>
                        </extensionsList>
                        <objectName>Outage Name</objectName>
                        <!-- more elements -->
                    </outageEvent>
                    <outageEvent objectID="2021-10-16-0001">
                        <comments>Test outage 1</comments>
                        <!-- more elements -->
                    </outageEvent>
                </oEvents>
            </OutageEventChangedNotification>
        </soap:Body>
    </soap:Envelope>
    

    C#代码:

    XElement outages = XElement.Parse(requestBody);
                XNamespace oecn = "http://www.multispeak.org/Version_4.1_Release";
    //This works
                IEnumerable<string> outageIDs = from outage in outages.Descendants(oecn + "outageEvent")
                                                       select (string) outage.Attribute("objectID");
    
                foreach (string outageID in outageIDs)
                {
                    Console.WriteLine($"IENUMERABLE: {outageID}");
                }
    
    //This works
                IEnumerable<string> outageProperties = from outage in outages.Descendants(oecn + "outageEvent")
                                                       select (string)outage;
    
                foreach (string outageProperty in outageProperties)
                {
                    Console.WriteLine($"IENUMERABLE: {outageProperty} \r\n");
                }
    
    //This Doesn't
                var alloutages = from outage in outages.Descendants(oecn + "outageEvent")
                                      select new /*Error Here*/
                                  {
                                      outageID = outage.Attribute("objectID").Value,
                                      comments = outage.Element("comments").Value
                                  };
                                                
    
                foreach (var outage in alloutages)
                {
                    Console.WriteLine($"OUTPUT: {outage.outageID}");
                }
    

    输出

    Hello World!
    IENUMERABLE: 2021-10-16-0002
    IENUMERABLE: 2021-10-16-0001
    IENUMERABLE: Test outage 2primaryCrewPrimary Crew NamestringOutage Name0032.427326-99.788595TRANSFORMER1District9TRANSFORMER1TransformerA10FeederNameAssumed2015-01-01T10:00:00Z2015-01-01T10:30:00Z2015-01-01T11:00:00ZCrew1Crew21010Contractor44
    
    IENUMERABLE: Test outage 1primaryCrewPrimary Crew NamestringOutage Name0032.427326-99.788595TRANSFORMER1District9TRANSFORMER1TransformerA10FeederNameAssumed2015-01-01T10:00:00Z2015-01-01T10:30:00Z2015-01-01T11:00:00ZCrew11010Contractor44
    

    var=alloutages部分出现错误,突出显示“select new”块。

    System.NullReferenceException
      HResult=0x80004003
      Message=Object reference not set to an instance of an object.
      Source=ParseXMLWithLinq
      StackTrace:
       at XMLParse.Program.<>c.<Main>b__0_2(XElement outage) in
    
    System.Xml.Linq.XContainer.Element(...) returned null.
    

    变异体的内容如下所示:

    <outageEvent objectID="2021-10-16-0002" xmlns="http://www.multispeak.org/Version_4.1_Release">
      <comments>Test outage 2</comments>
      <extensionsList>
        <extensionsItem>
          <extName>primaryCrew</extName>
          <extValue>Primary Crew Name</extValue>
          <extType>string</extType>
           ...
    </outageEvent>
    
    1 回复  |  直到 4 年前
        1
  •  1
  •   Evk    4 年前

    异常的原因是 comments 元素内部 outageEvent 与在同一命名空间中 outageEvent ,所以在 http://www.multispeak.org/Version_4.1_Release 。因此,不要:

    select new /*Error Here*/
    {
        outageID = outage.Attribute("objectID").Value,
        comments = outage.Element("comments").Value
    };
    

    您需要做到:

    select new /*Error Here*/
    {
        outageID = outage.Attribute("objectID").Value,
        // use namespace you already have here
        comments = outage.Element(oecn + "comments").Value
    };
    

    另一种方法是按本地名称筛选元素:

    select new /*Error Here*/
    {
        outageID = outage.Attribute("objectID").Value,
        comments = outage.Elements().First(c => c.Name.LocalName == "comments").Value
    };
    
    推荐文章