I added a root element and closing tag for the messages to make the XML valid:
XDocument loaded = XDocument.Parse(@"
<messages>
<message name=""Person"" id=""P"">
<field name=""FirstName"" required=""Y"" />
<field name=""LastName"" required=""Y"" />
<field name=""Sex"" required=""N"" />
</message>
<message name=""Car"" id=""C"">
<field name=""Make"" required=""Y"" />
<field name=""Model"" required=""Y"" />
<field name=""Year"" required=""N"" />
</message>
</messages>");
Instead of looking up all fields and then check the parent for each of them, look up the one parent that you are interrested in so that you have less fields to examine:
IEnumerable<string> fields =
loaded.Root.Elements()
.Where(m => m.Attribute("id").Value == "P")
.Single()
.Elements("field")
.Where(f => f.Attribute("required").Value == "Y")
.Select(f => f.Attribute("name").Value);
Edit:
Added the specifier "field" for the child elements in case the message element contains any other kinds of elements.
Edit 2:
I put together a working example with a subset of the actual data:
XDocument loaded = XDocument.Parse(@"
<fix major=""4"" minor=""4"">
<header>
</header>
<trailer>
</trailer>
<messages>
<message name=""ResendRequest"" msgtype=""2"" msgcat=""admin"">
<field name=""BeginSeqNo"" required=""Y"" />
<field name=""EndSeqNo"" required=""Y"" />
</message>
<message name=""Reject"" msgtype=""3"" msgcat=""admin"">
<field name=""RefSeqNum"" required=""Y"" />
<field name=""RefTagID"" required=""N"" />
<field name=""RefMsgType"" required=""N"" />
<field name=""SessionRejectReason"" required=""N"" />
<field name=""Text"" required=""N"" />
<field name=""EncodedTextLen"" required=""N"" />
<field name=""EncodedText"" required=""N"" />
</message>
</messages>
</fix>");
IEnumerable<string> fields =
loaded.Root.Element("messages").Elements("message")
.Where(m => m.Attribute("name").Value == "Reject")
.Single()
.Elements("field")
.Where(f => f.Attribute("required").Value == "Y")
.Select(f=>f.Attribute("name").Value);