简体   繁体   English

使用XPathNavigator.Select(xpath)找不到节点

[英]No nodes found with XPathNavigator.Select(xpath)

I'm creating C# console application to view stop number, name, location (latitude&longitude), and route number. 我正在创建C#控制台应用程序以查看站点号,名称,位置(纬度和经度)和路线号。 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 . 并在IE中打开xml文件,我已经创建了XSLT,并且XML文件遵循此Question Xpath和XSLT来将选定的数据显示为html I have added Xpath expression to query the stop by name to be like this: 我添加了Xpath表达式以按名称查询stop,如下所示:

XSLT 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格式

<?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 C#控制台应用

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 我添加了Xpath表达式以按名称查询stop,如下所示:XSLT

First, an XSLT stylesheet is not "Xpath expression" (though it contains XPath expressions). 首先,XSLT样式表不是“ Xpath表达式”(尽管它包含XPath表达式)。

Second, your XSLT stylesheet references an undeclared variable $theStreet on line 12. 其次,您的XSLT样式表在第12行引用了一个未声明的变量$theStreet

-- -
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. 我不知道如何在C#中执行此操作,但是您的样式表必须先声明此类参数,然后才能为其接收值。

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? 看起来您想要做的是在XSLT中动态添加一个变量声明以创建一个新的XSLT,然后将其保存并用于显示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. 可以尝试向XSLT样式表中添加一个参数,然后使用XSLCompiledTransform在程序本身中执行转换,并以此传递参数,而不是尝试通过添加新语句然后在浏览器中打开XML来修改XSLT。 ,然后在浏览器中打开结果HTML。

To start with you would have have an xsl:param in your XSLT . 首先,您的XSLT中应该有一个xsl:param (Directly under the xsl:stylesheet ) (直接位于xsl:stylesheet下

 <xsl:param name="theStreet" />

Then, you would use the XSLCompiledTransform class to actually perform the transformation to HTML. 然后,您将使用XSLCompiledTransform类实际执行到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. 然后打开的HTML应该只显示所选街道名称的详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM