简体   繁体   English

Linq to XML - 获取属性和元素

[英]Linq to XML - Get attribute and elements

Given this XML, how can I get data for each outageEvent including both attributes and elements?鉴于此 XML,我如何获取每个 outageEvent 的数据,包括属性和元素?

In the end, I need to move this data to a database, but doing this as a first step.最后,我需要将这些数据移动到数据库中,但这是第一步。

Desired end format is a 'row' for each outageEvent with the attribuite ObjectID and then the elements in outageEvent.所需的结束格式是每个带有属性 ObjectID 的 outageEvent 的“行”,然后是 outageEvent 中的元素。

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

Not necessary to get grandchildren of outageEvent such as ExtensionList children at this point.此时不需要获取 outageEvent 的孙子节点,例如 ExtensionList 子节点。

So far I am working on querying with Linq to XML.到目前为止,我正在使用 Linq to XML 进行查询。 I'm able to query and get the objectIDs.我能够查询并获取 objectID。 Separately, I am able to query to get all the elements.另外,我可以查询以获取所有元素。 Trying to combine the two is giving me problems.试图将两者结合起来给我带来了问题。 Haven't done any C# in a while, so that is 99% of the problem.有一段时间没有做任何 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# code: 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($"IENUMBERABLE: {outageID}");
            }

//This works
            IEnumerable<string> outageProperties = from outage in outages.Descendants(oecn + "outageEvent")
                                                   select (string)outage;

            foreach (string outageProperty in outageProperties)
            {
                Console.WriteLine($"IENUMBERABLE: {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}");
            }

Output:输出:

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

IENUMBERABLE: Test outage 1primaryCrewPrimary Crew NamestringOutage Name0032.427326-99.788595TRANSFORMER1District9TRANSFORMER1TransformerA10FeederNameAssumed2015-01-01T10:00:00Z2015-01-01T10:30:00Z2015-01-01T11:00:00ZCrew11010Contractor44

Error at var = alloutages section, highlighting the 'select new' block. var = alloutages 部分出错,突出显示“选择新”块。

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.

Contents of alloutages looks like this: alloutages 的内容如下所示:

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

The reason for exception is comments element inside outageEvent is in the same namespace as outageEvent , so in http://www.multispeak.org/Version_4.1_Release .之所以例外是comments元素里面outageEvent是在同一个命名空间outageEvent ,所以在http://www.multispeak.org/Version_4.1_Release So instead of:所以而不是:

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

You need to do:你需要做:

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

Alternative approach is to filter elements by local name:另一种方法是按本地名称过滤元素:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM