简体   繁体   中英

C# LINQ and XML Getting child nodes

Having issues getting node values. Not sure why the following code is failing to do so.

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='STIG_unclass.xsl'?>
<Benchmark xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cpe="http://cpe.mitre.org/language/2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" id="Windows_7_STIG" xml:lang="en" 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://cpe.mitre.org/files/cpe-dictionary_2.1.xsd" xmlns="http://checklists.nist.gov/xccdf/1.1">
    <status date="2015-06-16">accepted</status>
    <title>Windows 7 Security Technical Implementation Guide</title>
    <description>
        The Windows 7 Security Technical Implementation Guide (STIG) is published as a tool to improve the security of Department of Defense (DoD) information systems.  The requirements were developed from DoD consensus, as well as the Windows 7 Security Guide and security templates published by Microsoft Corporation.  Comments or proposed revisions to this document should be sent via e-mail to the following address:  disa.stig_spt@mail.mil.
    </description>
    <notice id="terms-of-use" xml:lang="en">Developed_by_DISA_for_the_DoD</notice>
    <reference href="http://iase.disa.mil">
        <dc:publisher>DISA, Field Security Operations</dc:publisher>
        <dc:source>STIG.DOD.MIL</dc:source>
    </reference>
    <plain-text id="release-info">Release: 20 Benchmark Date: 24 Jul 2015</plain-text>
</Benchmark>

Sample XML File.

and the following is my code.

String Title = LoadedXML.Element("Benchmark").Attribute("id").Value;
var XMLData = LoadedXML.Element("Benchmark").Elements("plain-text")
                 .Single(release => release.Attribute("id").Value == "release-info").Value;

is there a way I can get multiple Node values at the same time? Like getting the Title and Release Value at once instead of having a separate one for each?

Linq-to-xml is generally used to query a XML to filter it's nodes and then get the desired element/values per need. It's more like querying a table with SQL.

If all/most of the XML is required as a result, then the better approach would be to deseralize the XMl into a native (C# here) object and map it to the required model object. XML can always be thought of a serialized version of an object (although it can be manually as well), and can be deserialized back to the actual object.

.Net has native support for all these, see msdn links for XML Serialization and Deserialization for details. You can write a small method to deserialize your object like this.

using System.Xml.Linq;
using System.Xml.Serialization;

public class XMLHelper
{
    public T DeserializeData<T>(string data)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        StringReader reader = new StringReader(data);
        var deserializedObject = serializer.Deserialize(reader);
        return deserializedObject == null ? default(T) : (T)deserializedObject;
    }
}

To get the string you can do like File.ReadAllText(xmlFilePath) or whatever is easier for the situation.

This will give you deseialized object of the whole XML. If you want some other transformed object, you can either manually map that, or use AutoMapper

Your code is failing because your XML contains Namespace and you can't access your nodes directly. If you want to confirm this simply query LoadedXML.Elements() and examine the values in debugger, you can clearly see the namespaces there:-

在此输入图像描述

So, You need to declare the namespace and use it:-

XNamespace ns = "http://checklists.nist.gov/xccdf/1.1";

If you want both vales to be fetched at once you can project it to a anonymous type like this:-

var result = LoadedXML.Root.Elements(ns + "plain-text")
                      .Where(x => (string)x.Attribute("id") == "release-info")
                      .Select(x => new
                             {
                                 Title = (string)x.Document.Root.Attribute("id"),
                                 XMLData = x.Value
                             }).FirstOrDefault();

This query is giving me below output:-

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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