简体   繁体   中英

No nodes found with XPathNavigator.Select(xpath)

I'm creating C# console application to view stop number, name, location (latitude&longitude), and route number. and open xml file in IE I have create XSLT and XML files follow this Question Xpath and XSLT to display selected data to html . I have added Xpath expression to query the stop by name to be like this:

XSLT

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:template match="/">
    <xsl:element name="html">
      <xsl:element name="body">
        <table style="width:720px" border="3">
          <tr>
            <td>Stop #</td>
            <td>Route #</td>
            <td>Name</td>
          </tr>
          <xsl:apply-templates select="//stop[@name=$theStreet]"/>
        </table>
      </xsl:element>
    </xsl:element>
  </xsl:template>
  <xsl:template match="stop">
    <tr>
      <td>
        <xsl:value-of select="@number"/>
      </td>
      <td>
        <xsl:value-of select="routes"/>
      </td>
      <td>
        <xsl:value-of select="@name"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

XML

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="ltcstops.xslt"?>
<allstops>
  <stop number="2504" name="Main &amp; Bainard EB">
    <location>
      <latitude>42.91033567</latitude>
      <longitude>-81.29671483</longitude>
    </location>
    <routes>28</routes>
  </stop>
  <stop number="20" name="Adelaide &amp; Ada NB">
    <location>
      <latitude>42.9742886</latitude>
      <longitude>-81.2252341</longitude>
    </location>
    <routes>16</routes>
  </stop>
  <stop number="22" name="Adelaide &amp; Central Ave NB">
    <location>
      <latitude>42.9945666</latitude>
      <longitude>-81.2343441</longitude>
    </location>
    <routes>16</routes>
  </stop>
  <stop number="24" name="Adelaide &amp; Cheapside St NB">
    <location>
      <latitude>43.0064704</latitude>
      <longitude>-81.2401808</longitude>
    </location>
    <routes>16</routes>
  </stop>
</allstops>

ERROR: Couldn't find the expected 'apply-templates' declaration!

C# console app

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Xml;       // XmlDocument class
using System.Xml.XPath; // XPathNavigator class
using System.IO;        // Directory class

namespace BusStopApplication
{
    class Program
    {

        private const string XML_FILE = @"Documents\Visual Studio 2012\Projects\C#Project\BusStopApplication\BusStopApplication\ltcstops.xml"; 

        private const string XSLT_FILE_IN = @"Documents\Visual Studio 2012\Projects\C#Project\BusStopApplication\BusStopApplication\ltcstops.xslt";    

        private const string XSLT_FILE_OUT = "..\\..\\ltcstops_modified.xslt";
        static void Main(string[] args)
        {

           XmlDocument doc = new XmlDocument();
            doc.Load(XSLT_FILE_IN);

            // Obtain an XPathNavigator object
            XPathNavigator nav = doc.CreateNavigator();


            XmlNamespaceManager context = new XmlNamespaceManager(nav.NameTable);
            context.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");

            XPathExpression expr = nav.Compile("//xsl:variable[@name='theStreet']/@select");
            expr.SetContext(context);
            XPathNodeIterator nodes = nav.Select(expr);

         try
         {

           if (nodes.MoveNext())
            {
                // Get user's selection
                Console.Write("\nEnter street name: ");
                string street = Console.ReadLine();

                // Build a new 'select' attribute string for the apply-templates element
                string selectString = "//stop[@name='" + street.ToUpper() + "']";

                // Replace the select attribute 
                nodes.Current.SetValue(selectString);

                // Write new XSLT doc
                doc.Save(XSLT_FILE_OUT);

                // Display the transformed XML file in Internet Explorer

                // NOTE 4: The rutime folder used by the Internet Explorer (IE) program is 
                // different from the one used by our C# program. So we're going to give
                // IE the absolute path to the XML file by using the GetCurrentDirectory() method.
                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo.FileName = "iexplore";
                proc.StartInfo.Arguments = Directory.GetCurrentDirectory().ToString() + "\\" + XML_FILE;
                proc.Start();
            }
            else
                Console.WriteLine("ERROR: Couldn't find the expected 'apply-templates' declaration!");
         }
         catch (System.Exception ex)
         {
             Console.WriteLine(ex.ToString());
         }

        }
    }
}

I have added Xpath expression to query the stop by name to be like this: XSLT

First, an XSLT stylesheet is not "Xpath expression" (though it contains XPath expressions).

Second, your XSLT stylesheet references an undeclared variable $theStreet on line 12.

--
It seems like you are trying to pass a parameter to the stylesheet at runtime. I don't know how one does that in C#, but your stylesheet must declare such parameter before it can receive a value for it.

It looks like what you are trying to do is add a variable declaration dynamically to your XSLT to create a new XSLT which is then saved and used in displaying the XML? Rather than work out why your code is not working, I would suggest you take a different approach to the problem.

Instead of trying to modify the XSLT by adding new statements and then opening the XML in the browser, you could add a parameter to your XSLT stylesheet, and use XSLCompiledTransform to perform the transformation in the program itself, passing in the parameter as it does so, and then open the resultant HTML in the browser.

To start with you would have have an xsl:param in your XSLT . (Directly under the xsl:stylesheet )

 <xsl:param name="theStreet" />

Then, you would use the XSLCompiledTransform class to actually perform the transformation to HTML. Here is a sample of the code (using a hard-coded street name in this case).

using System.Diagnostics;
using System.Xml;
using System.Xml.Xsl;

namespace ConsoleApplication1
{
  class Program
  {
    private const string XML_FILE = @"Documents\ltcstops.xml";
    private const string XSLT_FILE_IN = @"Documents\ltcstops.xslt";
    private const string HTML_FILE_OUT = @"Documents\ltcstops.html";

    static void Main(string[] args)
    {
      // Create the XslCompiledTransform and load the stylesheet.
      XslCompiledTransform xslt = new XslCompiledTransform();
      xslt.Load(XSLT_FILE_IN);

      // Create the XsltArgumentList.
      XsltArgumentList xslArg = new XsltArgumentList();

      // Create a parameter which represents the current date and time.
      string streetName = "Adelaide & Ada NB";
      xslArg.AddParam("theStreet", "", streetName);

      // Transform the file. 
      using (XmlWriter w = XmlWriter.Create(HTML_FILE_OUT))
      {
        xslt.Transform(XML_FILE, xslArg, w);
      }

      Process proc = new System.Diagnostics.Process();
      proc.StartInfo.FileName = "iexplore";
      proc.StartInfo.Arguments = HTML_FILE_OUT;
      proc.Start();
    }
  }
}

The HTML that is opened up should then just show the details of the selected street name.

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