简体   繁体   中英

LINQ query to get XML elements when an attribute is not present

I have this XML:

<Config>
  <EmpFieldsMap>
    <Employee>
      <Field>
        <Name update = "false">EmpNumber</Name>
      </Field>
      <Field>
        <Name insert = "true">EmpName</Name>
      </Field>
      <Field>
        <Name insert = "true">EmpDesignation</Name>
      </Field>
    </Employee>
  </EmpFieldsMap>
</Config>

My application will do an an INSERT or UPDATE for which the fields will come from this xml. Each tag will have either the insert or the update attribute as shown in the snippet above.

For Insert all the tags that have the attribute

insert = "true"

and the tags that don't have this attribute, in this case the 'EmpNumber', have to be considered.

The same applies for update.

This code gives me all the tags with the insert attribute set to true:

insertTags = from p in xml.Element("Config").Element("EmpFieldsMap").Elements("Field")
             where p.Element("Name").Attribute("insert") != null 
             && p.Element("Name").Attribute("insert").Value == "true"
             select p.Element("Name").Value;

Removing the check for null

insertTags = from p in xml.Element("Config").Element("EmpFieldsMap").Elements("Field")
             where p.Element("Name").Attribute("insert").Value == "true"
             select p.Element("Name").Value;

gives

Object Reference not set to an instance

error.

I am having trouble composing a query that will also include the tags where the attribute is not present.

Can someone please help me with this?

Regards.

insertTags = from p in xml.Element("Config").Element("EmpFieldsMap").Elements("Field")
    where (p.Element("Name").Attribute("insert") ?? "true") == "true"
    select p.Element("Name").Value;

With XPath and Linq it even simpler:

XPathSelectElements(@"Config/EmpFieldsMap/Employee/Field/Name[@insert='true']")

Also for this particular xml you can use global search for name elements:

var insertTags = xdoc.XPathSelectElements(@"//Name[@insert='true']")
                     .Select(n => (string)n);

Or with Linq query syntax:

var insertTags = from n in xdoc.Descendants("Name")
                 where (string)n.Attribute("insert") == "true"
                 select (string)n;

When you cast node value to string, it will not throw exception if node is missing. Simply null will be returned. So, you don't need all that stuff (which is btw even not compilable ):

(p.Element("Name").Attribute("insert") ?? "true") == "true"

One more edit . If you are dealing with booleans, then use booleans instead of strings:

var insertTags = from n in xdoc.Descendants("Name")
                 where (bool?)n.Attribute("insert") == true
                 select (string)n;

How it works? Nullable boolean will have null value for missing attributes. Comparing bool? which do not have value with any boolean value produces false . So, you will get only those elements, which have required attribute, and which have true for that attribute.

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