XPathNavigator.Select(xpath)找不到任何节点

时间:2014-04-03 04:54:30

标签: c# xml xslt xpath

我正在创建C#控制台应用程序以查看停靠号码,名称,位置(纬度和经度)以及路线编号。在IE中打开xml文件我已创建XSLT和XML文件,请遵循此问题Xpath and XSLT to display selected data to html。我添加了Xpath表达式来查询stop by name:

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>
  

错误:无法找到预期的&#39; apply-templates&#39;声明!

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());
         }

        }
    }
}

2 个答案:

答案 0 :(得分:0)

  

我已经添加了Xpath表达式来查询停止名称   这个:XSLT

首先,XSLT样式表不是“Xpath表达式”(尽管它包含XPath表达式)。

其次,您的XSLT样式表在第12行引用了未声明的变量$theStreet

-
您似乎试图在运行时将参数传递给样式表。我不知道在C#中如何做到这一点,但你的样式表必须先声明这样的参数才能接收到它的值。

答案 1 :(得分:0)

看起来你要做的是动态地向XSLT添加一个变量声明来创建一个新的XSLT然后保存并用于显示XML?我建议您采用不同的方法解决问题,而不是弄清楚为什么你的代码不起作用。

您可以通过添加新语句然后在浏览器中打开XML来尝试修改XSLT,而不是在XSLT样式表中添加参数,并使用XSLCompiledTransform在程序本身中执行转换,并通过在参数中,然后在浏览器中打开生成的HTML。

首先,您的XSLT中会有 xsl:param 。 (直接在 xsl:stylesheet 下)

 <xsl:param name="theStreet" />

然后,您将使用XSLCompiledTransform类实际执行到HTML的转换。以下是代码示例(在这种情况下使用硬编码的街道名称)。

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();
    }
  }
}

打开的HTML应该只显示所选街道名称的详细信息。