Reputation: 84590
This MSDN page shows how to use Linq-to-XML to find XML nodes that contain a certain child node. Unfortunately, I have the opposite problem: I have a large list and a few of those nodes are missing a certain child node that should be there. Is there any good way to find them?
For example:
<Objects>
<Object>
<ID>1</ID>
<A>1</A>
<B>1</B>
<C>1</C>
</Object>
<Object>
<ID>2</ID>
<A>2</A>
<B>2</B>
<C>2</C>
</Object>
<Object>
<ID>3</ID>
<A>3</A>
<C>3</C>
</Object>
<Object>
<ID>4</ID>
<A>4</A>
<B/>
<C>4</C>
</Object>
</Objects>
How would I set up code to find all <Object>
elements with a missing <B>
node, which would return #3, but not #4?
Upvotes: 3
Views: 2097
Reputation: 11182
Here is another work-around, if you like to utilize the XPath
for this case, you may use the below approach also:
static void Main(string[] args)
{
XElement objects = XElement.Parse(@"<Objects>
<Object>
<ID>1</ID>
<A>1</A>
<B>1</B>
<C>1</C>
</Object>
<Object>
<ID>2</ID>
<A>2</A>
<B>2</B>
<C>2</C>
</Object>
<Object>
<ID>3</ID>
<A>3</A>
<C>3</C>
</Object>
<Object>
<ID>4</ID>
<A>4</A>
<B/>
<C>4</C>
</Object>
</Objects>");
string xpath_string = "//Object[count(B) = 0]"; //you can change the name of the element anytime,
//even in the run-time also... just make sure
//to add `System.Xml.XPath` to utilize the XPath...
IEnumerable<XElement> query_for_objects = objects.XPathSelectElements(xpath_string);
foreach (XElement ele in query_for_objects)
{
Console.WriteLine(ele.ToString());
}
Console.ReadKey();
What is nice using XPath
for this case, you may use a customized query even at run-time also, without changing your code at all!
Upvotes: 2
Reputation: 1799
This works because XContainer.Element("elementName")
returns null
if elementName
doesn't exist (note: I copied your xml into a string called xml
, so you need to just do .Descendents
on your XDocument
):
static void Main(string[] args)
{
var elementsWithoutB = XDocument.Parse(xml)
.Descendants("Object")
.Where(x => x.Element("B") == null);
// Prove it works by printing the elements returned
foreach (var element in elementsWithoutB)
{
Console.WriteLine(element.ToString());
}
Console.Read();
}
Upvotes: 2