.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.