Chris
Chris

Reputation: 934

C# Get Xelement Attribute Value by Attribute Name

I'm trying to get the value of operating-system attribute in the xml code below but in all of the solutions I've tried so far from stack, dotnetcurry, and Microsoft, I get either a NullPointerExecption or it just returns no values.

Here is the xml data I'm trying to parse:

<Report name="Black Workstation" xmlns:cm="http://www.nessus.org/cm">
  <ReportHost name="192.168.1.000>
    <HostProperties>
        <tag name="HOST_END">Wed Jun 29 10:32:54 2016</tag>
        <tag name="LastAuthenticatedResults">1467214374</tag>
        <tag name="patch-summary-total-cves">5</tag>
        <tag name="cpe">cpe:/o:microsoft:windows</tag>
        <tag name="operating-system">Microsoft Windows 7 Enterprise Service Pack 1</tag>
    </HostProperties>
  </ReportHost>
</Report>

I've tried numerous methods but here are the last two:

XNamespace ns = "http://www.nessus.org/cm";
var operatingSystem = (findings.Where(a => a.Attribute("name").Value == "operating-system")
.Select(a => a.Value));                                        

var operatingSystem = findings.Descendants().Where(x => x.Attribute("name").Value == ns + "operating-system");

Also tried this solution: Use Linq to Xml with Xml namespaces

I have this method here from the Microsoft tutorial but it only returns true/false and I am not able to manipulate it such that it assigns the value Microsoft Windows 7 Enterprise Service Pack 1 to the os variable.

XElement xelement = XElement.Load(s);
IEnumerable<XElement> findings = xelement.Elements();

var hostProperties = from hp in findings.Descendants("HostProperties")
                     select new
                     {
                         os = (string)hp.Element("tag").Attribute("name").Value == "operating-system",
                     };

I've tried using various other Linq-to-Xml queries with the where clause like above but they all return Null or no values to enumerate.

Upvotes: 4

Views: 7973

Answers (2)

Sangeeth Gv
Sangeeth Gv

Reputation: 9

please try the following

 XDocument document = XDocument.Load("content.xml");
 var name = document.XPathSelectElement("Report/ReportHost/HostProperties/tag[@name='operating-system']").Value;

Upvotes: 0

Gilad Green
Gilad Green

Reputation: 37281

In your case you do not need to apply a namespace:

var result = XDocument.Load("data.xml")
                      .Descendants("tag")
                      .Where(e => e.Attribute("name").Value == "operating-system")
                      .FirstOrDefault()?.Value;

 //result = Microsoft Windows 7 Enterprise Service Pack 1

Reading a bit more into it here you can actually see that even though you define a namespace in your xml none of your elements use it. The namespace you defined (xmlns:cm) is applied only to elements with the cm: prefix, and their are non of them.

See that if I change your xml as following (namespace is only for xmlns and not xmlns:cm):

<Report name="Black Workstation" xmlns="http://www.nessus.org/cm"> 
  <ReportHost name="192.168.1.000">
  <HostProperties>
    <tag name="HOST_END">Wed Jun 29 10:32:54 2016</tag>
    <tag name="LastAuthenticatedResults">1467214374</tag>
    <tag name="patch-summary-total-cves">5</tag>
    <tag name="cpe">cpe:/o:microsoft:windows</tag>
    <tag name="operating-system">Microsoft Windows 7 Enterprise Service Pack 1</tag>
  </HostProperties>
</ReportHost>
</Report>

The above code will return null and you will have to write is like this:

XNamespace ns = "http://www.nessus.org/cm";
var result = XDocument.Load("data.xml")
                      .Descendants(ns + "tag")
                      .Where(e => e.Attribute("name").Value == "operating-system")
                      .FirstOrDefault()?.Value;

Upvotes: 4

Related Questions