Cannot get child nodes of a specific type that contain a specific text

Using the code below, I can receive all the <job> elements in my Xml. However, when I try to search for jobs that have a child called <Name> and their text equals "receiverjob", the SelectNodes() method returns zero even though the job exists.

XmlDocument dom = new XmlDocument();
dom.Load(textBoxFilePath.Text);
XmlNamespaceManager nsManager = new XmlNamespaceManager(dom.NameTable);
nsManager.AddNamespace("d", "http://quartznet.sourceforge.net/JobSchedulingData");
XmlNodeList jobElements = dom.DocumentElement.SelectNodes("descendant::d:job[name=receiverjob]", nsManager);

Xml:

<?xml version="1.0" encoding="UTF-8"?>
<!-- This file contains job definitions in schema version 2.0 format -->
<job-scheduling-data version="2.0" xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <processing-directives>
    <overwrite-existing-data>true</overwrite-existing-data>
  </processing-directives>
  <schedule>
    <job>
      <name>receiverjob</name>
      <group>receivergroup</group>
      <job-type>Quartz.Server.ArgumentReceiverJob, Quartz.Server</job-type>
      <job-data-map>
        <entry>
          <key>receivedargument</key>
          <value>hamburger</value>
        </entry>
      </job-data-map>
    </job>
    <trigger>
      <simple>
        <name>argumentreceiverJobTrigger</name>
        <group>argumentreceiverGroup</group>
        <description>Simple trigger to simply fire sample job</description>
        <job-name>receiverjob</job-name>
        <job-group>receivergroup</job-group>
        <misfire-instruction>SmartPolicy</misfire-instruction>
        <repeat-count>-1</repeat-count>
        <repeat-interval>10000</repeat-interval>
      </simple>
    </trigger>
    <job>
      <name>batchjob</name>
      <group>batchGroup</group>
      <job-type>Quartz.Server.BatchJob, Quartz.Server</job-type>
      <durable>true</durable>
      <recover>false</recover>
    </job>
    <trigger>
      <cron>
        <name>Trigger2</name>
        <group>DEFAULT</group>
        <job-name>batchjob</job-name>
        <job-group>batchGroup</job-group>
        <cron-expression>0/15 * * * * ?</cron-expression>
      </cron>
    </trigger>
    <job>
      <name>jobnamexxx</name>
    </job>
    <job>
      <name>jobnamexxx</name>
    </job>
    <job>
      <name>jobnamexxx</name>
    </job>
  </schedule>
</job-scheduling-data>
Jon Skeet
people
quotationmark

I'm not an XPath expert, but I suspect your query now is trying to find jobs where the name element is equal to a receiverjob element. I suspect you want something like this:

"descendant::d:job[name/text()='receiverjob']"

It's also possible that you need to qualify the name element to be in the right namespace:

"descendant::d:job[d:name/text()='receiverjob']"

I would strongly consider using LINQ to XML instead, however, where it would be really simple (IMO):

XDocument doc = XDocument.Load(textBoxFilePath.Text);
XNamespace ns = "http://quartznet.sourceforge.net/JobSchedulingData";
var jobs = doc.Descendants(ns + "job")
              .Where(x => (string) x.Element(ns + "name") == "receiverjob");

I'm uncertain about the XPath syntax, but I'm confident about the LINQ to XML version - which in itself is a mark of the benefit of that solution, IMO. (Of course, to an XPath expert who hadn't used LINQ to XML, the opposite might be true.)

people

See more on this question at Stackoverflow