Search code examples
c#xmlnamespacesxelement

LinQ to XML access elements and their values


Sorry for my bad english...

I try to get an enum of the elements "Member" and their values from my example XML-Code. This Code is generated by an external program. i shrink this xml-file to an example.


    <?xml version="1.0" encoding="utf-8"?>
    <Document>
    <SW.Types.PlcStruct ID="0">
        <AttributeList>
            <Interface>
                <Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v4">
                    <Section Name="None">
                        <Member Name="FirstMember" Datatype="Word"><AttributeList><BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute></AttributeList><Comment><MultiLanguageText Lang="de-DE">FirstMemberComment</MultiLanguageText></Comment></Member>
                        <Member Name="SecondMember" Datatype="Word"><AttributeList><BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute></AttributeList><Comment><MultiLanguageText Lang="de-DE">SecondMemberComment</MultiLanguageText></Comment></Member>
                    </Section>
                </Sections>
            </Interface>
        </AttributeList>
    </SW.Types.PlcStruct>
    </Document>

i get down until the "Interface" Element, but beyond this i can not access the data.

XElement xelement = XElement.Load(xmlPath);
IEnumerable<XElement> udtContent = xelement.Element("SW.Types.PlcStruct").Element("AttributeList").Element("Interface").Elements();

is this because of that xmlns namespace tag in that xml file? if i debug now udtContent i get this:

{<Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v4">
<Section Name="None">
   <Member Name="FirstMember" Datatype="Word">
      <AttributeList>
         <BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
      </AttributeList>
      <Comment>
         <MultiLanguageText Lang="de-DE">FirstMemberComment</MultiLanguageText>
      </Comment>
    </Member>
    <Member Name="SecondMember" Datatype="Word">
      <AttributeList>
        <BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
      </AttributeList>
      <Comment>
        <MultiLanguageText Lang="de-DE">SecondMemberComment</MultiLanguageText>
      </Comment>
    </Member>
  </Section>
</Sections>}

hope you can give me a hint how to get an enum of that "Member" elements...


Solution

  • Namespace is the issue. You can use code like this

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    
    namespace ConsoleApplication2
    {
        class Program
        {
            const string FILENAME = @"c:\temp\test.xml";
            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load(FILENAME);
    
                List<XElement> members = doc.Descendants().Where(x => x.Name.LocalName == "Member").ToList();
                XNamespace ns = members.FirstOrDefault().GetDefaultNamespace();
    
                foreach (XElement member in members)
                {
                    foreach (XElement booleanAttribute in member.Descendants(ns + "BooleanAttribute"))
                    {
                        string name = (string)booleanAttribute.Attribute("Name");
                    }
                }
            }
        }
    }