Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Linq-to-XML on XCCDF

I'm trying to parse out information from a XCCDF output file but my Linq-to-Xml queries keep returning empty. Here are some of the ones I've tried to this point:

XElement xelement = XElement.Load(s);
IEnumerable<XElement> findings = xelement.Elements();
XNamespace ns = "http://checklists.nist.gov/xccdf/1.1";

var findingDetails = from f in findings.Descendants(ns + "Benchmark")
                     select new
                     {
                         title = f.Element("title").Value            
                     };

foreach (var fd in findingDetails)
{
    Console.WriteLine(fd.ToString());
}

I also tried:

var findingDetails = from f in findings.Descendants(ns + "Benchmark")
                     select f;

var findingDetails = from f in findings.Descendants("Benchmark")
                     select new
                     {
                         title = f.Element("title").Value             
                     };

var findingDetails = from f in findings.Elements(ns + "Benchmark")
                     select new
                     {
                         title = f.Element("title").Value             
                     };

var findingDetails = from f in findings.Elements(ns + "Benchmark")
                     select f;

Here is a condensed version of the xccdf.xml file. Based on this version how would I get the title "Red Hat..." (line 5) and the title "daemon umask" (line 19)? (I do understand that my examples above do not attempt to get this data, I had to break it down to just trying to get anything...

<?xml version="1.0" encoding="UTF-8"?>

<cdf:Benchmark style="SCAP_1.1" resolved="1" id="RHEL_6_STIG" xsi:schemaLocation="http://checklists.nist.gov/xccdf/1.1 http://nvd.nist.gov/schema/xccdf-1.1.4.xsd http://cpe.mitre.org/dictionary/2.0 http://scap.nist.gov/schema/cpe/2.2/cpe-dictionary_2.2.xsd" xmlns:cdf="http://checklists.nist.gov/xccdf/1.1" xmlns:cpe="http://cpe.mitre.org/dictionary/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <cdf:status date="2016-04-22">accepted</cdf:status>
  <cdf:title>Red Hat Enterprise Linux 6 Security Technical Implementation Guide</cdf:title>
  <cdf:description>The Red Hat Enterprise Linux 6 Security Technical Implementation Guide (STIG) is published as a tool to improve the security of Department of Defense (DoD) information systems.  Comments or proposed revisions to this document should be sent via e-mail to the following address: [email protected].</cdf:description>
  <cdf:notice id="terms-of-use"></cdf:notice>
  <cdf:reference href="http://iase.disa.mil">
        <dc:publisher>DISA</dc:publisher>
        <dc:source>STIG.DOD.MIL</dc:source>
  </cdf:reference>
  <cdf:plain-text id="release-info">Release: 11 Benchmark Date: 22 Apr 2016</cdf:plain-text>
  <cdf:platform idref="cpe:/o:redhat:enterprise_linux:6"></cdf:platform>
  <cdf:version>1</cdf:version>
  <cdf:Profile id="MAC-1_Classified">
        <cdf:title>I - Mission Critical Classified</cdf:title>            
  </cdf:Profile>
  <cdf:Value id="var_umask_for_daemons">
        <cdf:title>daemon umask</cdf:title>
        <cdf:description>Enter umask for daemons</cdf:description>
        <cdf:value>022</cdf:value>
        <cdf:value selector="022">022</cdf:value>
        <cdf:value selector="027">027</cdf:value>
  </cdf:Value>
</cdf:Benchmark>
like image 782
Chris Avatar asked Mar 12 '23 07:03

Chris


2 Answers

Both Benchmark and title have the namespace http://checklists.nist.gov/xccdf/1.1, so you need to use this if you're going to query for title.

Secondly, you parse using XElement.Parse, so the result is an element representing the Benchmark element. You then get its child elements (status to Value). Then you search for descendants of any of those called Benchmark - you're not going to find any, as Benchmark was where you started.

This should work:

var element = XElement.Load(s);

var findingDetails = new
{
    title = (string)element.Element(ns + "title")
};

Alternatively, load as a document:

var doc = XDocument.Load(s);

var findingDetails =
    from benchmark in doc.Descendants(ns + "Benchmark")
    select new
    {
        title = (string)benchmark.Element(ns + "title")
    };
like image 53
Charles Mager Avatar answered Mar 27 '23 17:03

Charles Mager


Try following

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ProgrammingBasics
{
    class Exercise
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main()
        {
            XDocument doc = XDocument.Load(FILENAME);
            var results = doc.Descendants().Where(x => x.Name.LocalName == "Benchmark").Select(y => new
            {
                title = (string)y.Elements().Where(z => z.Name.LocalName == "title").FirstOrDefault()
            }).FirstOrDefault();
        }

    }

}
like image 21
jdweng Avatar answered Mar 27 '23 16:03

jdweng