Следует отметить две вещи :
Гораздо более естественно применить преобразование к результату вызова метода GetResultTable()
, чем получить его результат с помощью функции расширения.
Как написано, метод GetResultTable()
вообще не возвращает ни одного узла: в операторе
-
return doc.CreateNavigator().Select("root");
метод Select()
ничего не выбирает, так как в doc
нет элемента root
. Элемент с именем Root
не выбран, так как XML и XPath чувствительны к регистру.
Другое наблюдение состоит в том, что совсем не обязательно использовать xsl:for-each
в XSLT-преобразовании - в большинстве случаев это считается плохой практикой.
Сказав это, вот полный код того, что задает этот вопрос :
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>