使用Xpath覆盖XSLT扩展方法的返回值

时间:2011-07-10 18:24:54

标签: c# xslt xpath methods

我有一个扩展方法返回的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本身的示例,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

有两点需要注意

  1. 将变换应用于调用方法GetResultTable()的结果比通过扩展函数获取结果更自然。

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

  3. -

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

    Select()方法未选择任何内容,因为root中没有doc元素。未选择名为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>