2

I'm trying to select the values from two adjacent xml nodes at the same time using

var values =
            xDoc.Element("root")
                .Elements("model")
                .Where(x => x.Element("modelName").Value == modelType.ToString())
                .Elements("directory")
                .Select(x => new { x.Element("directoryName").Value,
                               x.Element("taskName").Value });

I'm getting red squiggles under the .Values saying "Duplicate anonymous type property name 'Value'. Here is the xml

    <root>
  <model>
    <modelName>Model1</modelName>
    <directory>
      <directoryName>Dir1</directoryName>
      <taskName>Task1</taskName>
    </directory>
  </model>
  <model>
    <modelName>Model2</modelName>
    <directory>
      <directoryName>FirstValue</directoryName>
      <taskName>SecondValue</taskName>
    </directory>
  </model>
</root>

I want to extract Dir1 and Task1 or FirstValue and SecondValue.

2 Answers 2

3

I suggest you to use casting elements to string instead of accessing their Value property. Because if element is missing (e.g. for Model1 you don't have taskName element) then you will get NullReferenceException.

var values = from m in xDoc.Root.Elements("model")
             where (string)m.Element("modelName") == modelType.ToString()
             let d = m.Element("directory")
             select new {
                Directory = (string)d.Element("directoryName"),
                Task = (string)d.Element("taskName")
             };

Also I find declarative (query) syntax more readable than lambda syntax (matter of taste). You can also use XPath to make query even more compact:

string xpath = String.Format("root/model[modelName='{0}']/directory", modelType);
var values = from d in xdoc.XPathSelectElements(xpath)
             select new {
                 Directory = (string)d.Element("directoryName"),
                 Task = (string)d.Element("taskName")
             };
Sign up to request clarification or add additional context in comments.

5 Comments

@reggaeguitar your code throws exception for sample xml you provided. Try it with modelType = "Model1"
It's in a method where you have to provide an enum for the model type, e.g ModelType.Model2 which will turn into the string "Model2" on the ToString() call. I just filled in the xml.
+1 for the xDoc.Root property, I was not aware of that.
@reggaeguitar thanks! BTW I added xpath sample which might by interesting to you
Very cool! I ran it through my unit tests and it passed with flying colors.
2

Figured it out, you just need to name the properties in the anonymous type

var values =
            xDoc.Element("root")
                .Elements("model")
                .Where(x => x.Element("modelName").Value == modelType.ToString())
                .Elements("directory")
                .Select(x => new { Directory = x.Element("directoryName").Value,
                                   Task = x.Element("taskName").Value });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.