0

I am trying to select all nodes using root.SelectNodes() with XPath. For reference, see msdn-documentation.

In the following document explained, you can also search for nodes that contain attributes (correct me if this is actually a wrong understanding).

So I used the following line of code:

XmlNodeList nodes = projectDoc.DocumentElement.SelectNodes("descendant::Compile[attribute::Include]");

And I am trying to read the following data:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <ItemGroup>
        <Compile Include="ArrayExtensions.cs" />
        <Compile Include="ArrayIterator.cs" />
        <Compile Include="AutoInitializeAttribute.cs" />
        <Compile Include="AutoInitializePriority.cs" />
        <Compile Include="AutoRegisterAttribute.cs" />
        <Compile Include="FormattableExtensions.cs" />
        <Compile Include="Mathematics\PrimeNumbers.cs" />
    </ItemGroup>
</Project>

As shown in the code-sample above, I want to get all the XmlNodes that contain the Include-attribute. However, when I execute my code, nodes contains 0 elements.

What am I doing wrong here?

2
  • I strongly suspect that the problem is the namespace - you should actually be looking for Compile elements in the http://schemas.microsoft.com/developer/msbuild/2003 namespace. Is there any reason you need to do this in XPath? With LINQ to XML this would be trivial. Commented Jun 11, 2014 at 8:31
  • No particular reason no, if you have a better solution that would be much appreciated! Also a solution to the question I provided would be awesome too, just for learning purposes. Commented Jun 11, 2014 at 8:32

1 Answer 1

1

I suspect the reason it's failing has nothing to do with the attribute part - it's failing to find the elements at all, as you've asked for just Compile elements, whereas there are only actually Compile elements in the namespace with the URI http://schemas.microsoft.com/developer/msbuild/2003.

Doing this with XPath probably requires the use of an XmlNamespaceManager which you'd then pass into another overload of SelectNodes. Personally I would use LINQ to XML instead though:

XDocument doc = XDocument.Load("myfile.xml");
XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
var elements = doc.Descendants(ns + "Compile")
                  .Where(x => x.Attribute("Include") != null);

In general, I find LINQ to XML to be a much cleaner API than the "old" XmlDocument-based API.

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

2 Comments

How can I use a Count on this? I don't see any XNodeList (or similar) in the XDocument-API. What I am trying to say is, what does this return? A list of elements or?
@Matthijs: It returns an IEnumerable<XElement>. You can use the Count() extension method just as with any other sequence. If you want a List<XElement>, just add a call to .ToList().

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.