.NET 3.5 XPath类和方法是否与XSLT 2.0兼容?
我想在使用match函数选择元素时使用正则表达式。我不希望使用外部库(例如saxon)来执行此操作。
解决方案
是的,3.5 XPathNavigator支持XSLT 2.0。
http://msdn.microsoft.com/zh-CN/library/system.xml.xpath.xpathnavigator.aspx
" System.Xml.XPath命名空间中的XPathNavigator类是一个抽象类,它定义了一个游标模型,以作为XQuery 1.0和XPath 2.0数据模型的实例来导航和编辑XML信息项。"
内置库中不支持XSLT 2.0中的某些功能(在单邮件列表中对此进行了讨论,但我找不到信息了)。但是大多数人从来没有遇到过不被支持的情况。
另一种选择是查看开放源码http://saxon.sourceforge.net/,它对2.0有很好的支持。
编辑(AB):以上接受的答案可能会造成混淆。根本没有任何支持,并且.NET中没有针对XPath 2.0或者XSLT 2.0功能的任何计划。
我认为以上答案是错误的。我找不到任何证据表明Microsoft支持XSLT 2.0。 XSLT!= XPath。
供将来参考,这是有关在.net中扩展xpath / xquery的一个不错的页面:
http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=64
我不相信这会持续到最后,所以我在这里复制:
XSLT是XML的转换语言。它允许服务器系统将源XML树转换为更适合客户端的形式。 XSLT使用节点模式来匹配模板以执行其转换。尽管它使复杂的转换相对简单,但是在某些情况下,我们可能不得不使用一些自定义类。
我们可能需要扩展XSLT的一些情况是:
1)调用自定义业务逻辑
2)根据权限执行不同的操作
3)对日期,字符串等执行复杂的格式化
4)甚至打电话给网络服务!
扩展XSLT的步骤
1)从XSLT(在C#中)创建要使用的自定义对象
CustomDate custDate = new CustomDate() ;
2)在XSLT名称空间声明(在XSLT文件中)内为自定义类提供自定义名称空间声明
<xsl:transform
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myCustDate="urn:custDate">
3)将自定义对象的实例传递给XSLT,并使用与上一步相同的名称空间(在C#中)
xslArgs.AddExtensionObject("urn:custDate", custDate) ;
4)使用XSLT中的对象(在XSLT文件中)
<xsl:value-of select="myCustDate:GetDateDiff(./joiningdate)"/>
样例代码
对于我们的示例,假设我们有一个XSLT工作表,我们需要在其中操纵日期。我们需要显示员工在公司的工作天数。由于XSLT没有本地日期操作功能,因此让我们为任务使用扩展对象。
using System ;
using System.IO ;
using System.Xml ;
using System.Xml.Xsl ;
using System.Xml.XPath ;
public class XsltExtension{
public static void Main(string[] args){
if (args.Length == 2){
Transform(args[0], args[1]) ;
}else{
PrintUsage() ;
}
}
public static void Transform(string sXmlPath, string sXslPath){
try{
//load the Xml doc
XPathDocument myXPathDoc = new XPathDocument(sXmlPath) ;
XslTransform myXslTrans = new XslTransform() ;
//load the Xsl
myXslTrans.Load(sXslPath) ;
XsltArgumentList xslArgs = new XsltArgumentList() ;
//create custom object
CustomDate custDate = new CustomDate() ;
//pass an instance of the custom object
xslArgs.AddExtensionObject("urn:custDate", custDate) ;
//create the output stream
XmlTextWriter myWriter = new XmlTextWriter("extendXSLT.html", null) ;
//pass the args,do the actual transform of Xml
myXslTrans.Transform(myXPathDoc,xslArgs, myWriter) ;
myWriter.Close() ;
}catch(Exception e){
Console.WriteLine("Exception: {0}", e.ToString());
}
}
public static void PrintUsage(){
Console.WriteLine("Usage: XsltExtension.exe <xml path> >xsl path<") ;
}
}
//our custom class
public class CustomDate{
//function that gets called from XSLT
public string GetDateDiff(string xslDate){
DateTime dtDOB = DateTime.Parse(xslDate) ;
DateTime dtNow = DateTime.Today ;
TimeSpan tsAge = dtNow.Subtract(dtDOB) ;
return tsAge.Days.ToString() ;
}
}
编译此代码,并使用提供的members.xml和memberdisplay.xsl运行此控制台应用程序。我们应该在同一文件夹中看到一个extendXSLT.html文件。打开此文件,请注意已经调用了我们的CustomDate类来计算员工进入公司的天数。
概括 :
XSLT是XML的强大转换语言,但是在.NET和C中使用扩展对象应确保我们可以轻松完成仅凭XSLT不可能或者很难完成的工作。
Members.xml:
<root>
<member>
<name>Employee1</name>
<joiningdate>01/01/1970</joiningdate>
<role>CTO</role>
</member>
<member>
<name>Employee2</name>
<joiningdate>24/07/1978</joiningdate>
<role>Web Developer</role>
</member>
<member>
<name>Employee3</name>
<joiningdate>15/12/1980</joiningdate>
<role>Tester</role>
</member>
</root>
Memberdisplay.xsl:
<xsl:transform
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myCustDate="urn:custDate">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="/">
<html>
<head>
<style>
TABLE.tblMaster
{
border-style: solid;
border-width: 1px 1px 1px 1px;
border-style: solid;
border-color: #99CCCC;
padding: 4px 6px;
text-align: left;
font-family:Tahoma,Arial;
font-size:9pt;
}
TD.tdHeader
{
FONT-WEIGHT: bolder;
FONT-FAMILY: Arial;
BACKGROUND-COLOR: lightgrey;
TEXT-ALIGN: center
}
</style>
</head>
<body>
<table width="50%" class="tblMaster">
<tr >
<td class="tdHeader">Employee</td>
<td class="tdHeader">Join date</td>
<td class="tdHeader">Days in company</td>
<td class="tdHeader">Role</td>
</tr>
<xsl:for-each select="/root/member">
<tr >
<td> <xsl:value-of select="./name"/> </td>
<td> <xsl:value-of select="./joiningdate"/> </td>
<td> <xsl:value-of select="myCustDate:GetDateDiff(./joiningdate)"/> </td>
<td> <xsl:value-of select="./role"/> </td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:transform>
我相信在这次讨论中的答案是误导的。我认为.NET 3.5不支持大多数XSL / T 2.0功能(如果有的话)。
一个例子:
在.NET 3.5下,对2.0函数的调用会给出以下错误消息:
'current-dateTime()'是未知的XSLT函数。
在讨论.NET对XSLT 2.0,XPath 2.0和XQuery 1.0的支持时,重要的是要区分语言本身和数据模型(XDM)。 .NET 3.5框架支持数据模型,但不支持语言。正如最近Microsoft的Pawel Kadluczka通过电子邮件向我解释的那样:
The sentence "instances of the XQuery 1.0 and XPath 2.0 Data Model" may be confusing but I believe it refers to W3C XQuery 1.0 and XPath 2.0 Data Model (XDM) spec (http://www.w3.org/TR/xpath-datamodel) that reads: [Definition: Every instance of the data model is a sequence.]. [Definition: A sequence is an ordered collection of zero or more items.] A sequence cannot be a member of a sequence. A single item appearing on its own is modeled as a sequence containing one item. Sequences are defined in 2.5 Sequences. [Definition: An item is either a node or an atomic value], In the case of XPath API - XPathNodeIterator is the sequence while XPathItem (XPathNavigator) represents the item.

