Search code examples
c#xmllinq-to-xmlxelement

How do I find a specific XML attribute in a specific place in an XDocument


I have an example of my XML below (which i'm converting from SGML to XML prior to the check but that's besides the point). The XML IS valid at the point of checking.

I need check the XDocument and find out if any of the <version> elements contained within the <status> section at the top of the file contain the attriubute "RNWB". I need to be explicit about the fact that i'm only interested in checking <version> elements that are children of <status> elements because there might be other <version> elements within the document which i don't care about.

<dmodule>
    <idstatus>
        <dmaddres>
            <dmc>Blah</dmc>
            <dmtitle><techname>System</techname><infoname>Introduction</infoname></dmtitle>
            <issno issno="006" type="revised"/>
            <issdate year="2016" month="11" day="30"/>
        </dmaddres>
        <status>
            <security class="2"/>
            <rpc></rpc>
            <orig></orig>
            <applic>
                <model model="2093">
                    <version version="BASE"></version>
                    <version version="RNWB"></version></model>
            </applic>
            <techstd>
                <autandtp>
                    <authblk></authblk>
                    <tpbase></tpbase>
                </autandtp>
                <authex></authex>
                <notes></notes>
            </techstd>
            <qa>
            <firstver type="tabtop"/></qa>
            <remarks></remarks>
        </status>
    </idstatus>
    <content>
        <refs><norefs></refs>
        <descript>
            <para0><title>Introduction</title>
                <para>The system many new features included which are safe and accurate blah blah blah.</para>
        </descript>
    </content>
</dmodule>

I've tried all sorts but can't seem to get a result. Here's one example of what i've tried:

var result = (from ele in doc.Descendants("applic").Descendants("version").Attributes("RNWB")
                                      select ele).ToList();

      foreach (var v in result)
      {
          File.Move(file, Path.Combine(outputFolder, fileName)); // move the file to the new folder

       }

Solution

  • If you have to be explicit that the version element is within a status element, then you need to be explicit about that in your query too. Your example doesn't include version anywhere.

    You then need to find a version attribute with the value RNWB. You're currently looking for an RNWB attribute, which doesn't exist.

    var hasFlag = doc
        .Descendants("status")
        .Descendants("version")
        .Attributes("version")
        .Any(x => x.Value == "RNWB");
    

    See this fiddle for a demo.