在XSLT扩展方法的返回值上使用Xpath

本文关键字:Xpath 返回值 XSLT 扩展 方法 | 更新日期: 2023-09-27 18:01:36

我有一个由扩展方法返回的xml。请问有人能帮我在这个xml上使用<xsl:for-each>吗?

public class CustomObj
{
    //function that gets called from XSLT
    public XPathNodeIterator GetResultTable()
    {
        DataTable table = new DataTable("Table1");
        table.Columns.Add("SourceCity");
        table.Columns.Add("DestinationCity");
        table.Columns.Add("Fare");
        table.Rows.Add(new object[] { "New York", "Las Vegas", "100" });
        table.Rows.Add(new object[] { "New York", "London", "200" });
        table.Rows.Add(new object[] { "New York", "New Delhi", "250" });
        StringWriter writer = new StringWriter();
        table.WriteXml(writer);
        XmlDocument doc = new XmlDocument();
        XmlElement root = doc.CreateElement("Root");
        root.InnerXml = writer.ToString();
        doc.AppendChild(root);
        return doc.CreateNavigator().Select("root");
    }
}

我想遍历这个xml。谁来帮帮我。我是XSLT的新手,如果您能提供有关给定xml本身的示例,我将不胜感激。

在XSLT扩展方法的返回值上使用Xpath

有两件事需要注意:

  1. 将转换应用于调用方法GetResultTable()的结果比通过扩展函数获得结果要自然得多。

  2. 如前所述,GetResultTable()方法根本不返回任何节点:在语句

,

   return doc.CreateNavigator().Select("root");

Select()方法不选择任何东西,因为doc中没有root元素。没有选择名为Root的元素,因为XML和XPath是区分大小写的。

另一个观察结果是,根本没有必要在XSLT转换中使用xsl:for-each——在大多数情况下,这被认为不是一个好的实践。

话虽如此,下面是这个问题对的完整代码:

namespace TestXml
{
    using System;
    using System.Data;
    using System.IO;
    using System.Xml;
    using System.Xml.XPath;
    using System.Xml.Xsl;
    class Program
    {
        static void Main(string[] args)
        {
            CustomObj co = new CustomObj();
            XPathNodeIterator xpni = co.GetResultTable();
            XslCompiledTransform xslt = new XslCompiledTransform(true);
            xslt.Load(@"..'..'My.xslt");
            XsltArgumentList xargs = new XsltArgumentList();
            xargs.AddExtensionObject("my:extension", co);
            XmlDocument fakeDoc = new XmlDocument();
            fakeDoc.LoadXml("<t/>");
            StringWriter sw = new StringWriter();
            xslt.Transform(fakeDoc.CreateNavigator(), xargs, sw);
            string result = sw.ToString();
            Console.Write(result);
        }
    }
    public class CustomObj
    {    //function that gets called from XSLT    
        public XPathNodeIterator GetResultTable()    
        {        
            DataTable table = new DataTable("Table1");        
            table.Columns.Add("SourceCity");        
            table.Columns.Add("DestinationCity");        
            table.Columns.Add("Fare");        
            table.Rows.Add(new object[] { "New York", "Las Vegas", "100" });        
            table.Rows.Add(new object[] { "New York", "London", "200" });        
            table.Rows.Add(new object[] { "New York", "New Delhi", "250" });        
            StringWriter writer = new StringWriter();        
            table.WriteXml(writer);        
            XmlDocument doc = new XmlDocument();        
            XmlElement root = doc.CreateElement("Root");        
            root.InnerXml = writer.ToString();        
            doc.AppendChild(root);        
            return doc.CreateNavigator().Select("Root");    
        }
    }
}

和文件My.xslt:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:extension"
 exclude-result-prefixes="my">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="/">
    <html>
      <table border="1">
        <tr>
          <td>Source</td>
          <td>Destination</td>
          <td>Fare</td>
        </tr>
        <xsl:apply-templates select="my:GetResultTable()/*/Table1"/>
      </table>
    </html>
  </xsl:template>
  <xsl:template match="Table1">
    <tr>
      <xsl:apply-templates/>
    </tr>
  </xsl:template>
  <xsl:template match="Table1/*">
    <td>
      <xsl:apply-templates/>
    </td>
  </xsl:template>
</xsl:stylesheet>

当应用程序执行时,生成所需的正确结果:

<html>
  <table border="1">
    <tr>
      <td>Source</td>
      <td>Destination</td>
      <td>Fare</td>
    </tr>
    <tr>
    <td>New York</td>
    <td>Las Vegas</td>
    <td>100</td>
  </tr>
    <tr>
    <td>New York</td>
    <td>London</td>
    <td>200</td>
  </tr>
    <tr>
    <td>New York</td>
    <td>New Delhi</td>
    <td>250</td>
  </tr>
  </table>
</html>