2

I want my Linq statement to fetch only customfield with name="Required" in the below example

   <root>
    <appinfo>
        <application app_id=1234 app_name="SomeName">
        <customfield name="Required" value="123" />
        <customfield name="Not Required" value="234" />
        <customfield name="Not Required" value="345" />
        <customfield name="Not Required" value="456" />
        <customfield name="Not Required" value="678" />
        </application>
    </appinfo>
    ...
    </root>

1234,SomeName,123 needs to be picked in this case

Below is the statement I tried. The commented Where does not work

 var appAI =
        from appinfo in doc.Root.Elements()

        let application = appinfo.Elements().First()
        let custom_field = application.Descendants()

        //.Where(x => (string)x.Attribute("name") == "Required" && (string)x.Attribute("value").Value !="" )
        select new
        {
            app_id = (string)application.Attribute("app_id"),
            app_name = (string)application.Attribute("app_name"),
            app_AI = custom_field

        };
2
  • Shouldn't x.Attribute("name") == "Required" be x.Attribute("name").Value == "Required"? Commented Sep 2, 2014 at 21:19
  • I tried both. No luck.. Commented Sep 2, 2014 at 21:26

2 Answers 2

1

This seemed to work for me:

var results = 
    from appInfo in d.Elements()
    let application = appInfo.Elements().First()
    let custom_field = application.Descendants()
        .Where(x => x.Attribute("name").Value == "Required" && x.Attribute("value").Value != "")
        .SingleOrDefault()
    select new
    {
        app_id = application.Attribute("app_id").Value,
        app_name = application.Attribute("app_name").Value,
        app_AI = custom_field.Attribute("value").Value
    };

I think your main problem was looking at d.Root.Elements instead of just d.Elements.

Example: https://dotnetfiddle.net/XVM1qz

Sign up to request clarification or add additional context in comments.

3 Comments

I had missed a root tag in my question. apologies.. I tried with d.Root.Elements(). I get the Object reference not set error
strange.. When I try on your fiddle link.. Even after adding root, it works fine
I have found the error . It is because , few nodes do not have a closing tag for application. Have replicated the same here dotnetfiddle.net/YUoL4N
0

See if this will work. Note that you can chain "Elements" and some of the other extension methods directly off of IEnumerable<T> to make it a bit simpler.

from app in doc.Elements("appinfo").Elements("application")
from cf in app.Elements("customfield")
where (string)cf.Attribute("name") == "Required"
select new
{
    app_id = (string)app.Attribute("app_id"),
    app_name = (string)app.Attribute("app_name"),
    app_AI = (string)cf.Attribute("value")
};

Descendants is very rarely a useful method because it can hide potential structural issues in your document. I wouldn't use it unless I was performing validation elsewhere (like with a XSD).

1 Comment

It worked .. with a minor change. . For my new XML, it has to be doc.Root.Elements . Also , cf.Attribute("value").Value != "" condition was added

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.