【发布时间】:2010-09-10 18:40:48
【问题描述】:
我想在使用 match 函数选择元素时使用正则表达式。我不希望使用外部库(例如 saxon)来执行此操作。
【问题讨论】:
我想在使用 match 函数选择元素时使用正则表达式。我不希望使用外部库(例如 saxon)来执行此操作。
【问题讨论】:
XSLT 2.0 中的某些内容在内置库中不受支持(在 mono 邮件列表中对此进行了讨论,但我再也找不到相关信息了)。但大多数人从不遇到不受支持的极端情况。
另一种选择是查看开源http://saxon.sourceforge.net/,它对 2.0 有很好的支持。
编辑(AB):上述接受的答案可能会令人困惑。根本不支持,.NET 中的任何 XPath 2.0 或 XSLT 2.0 函数都有 no plans in that direction。
【讨论】:
在讨论 .NET 对 XSLT 2.0、XPath 2.0 和 XQuery 1.0 的支持时,区分语言本身和数据模型 (XDM) 很重要。 .NET 3.5 框架支持数据模型,但不支持语言。正如微软的 Pawel Kadluczka 最近通过电子邮件向我解释的那样:
句子“XQuery 的实例” 1.0 和 XPath 2.0 数据模型”可能令人困惑,但我相信它指的是 W3C XQuery 1.0 和 XPath 2.0 数据 型号 (XDM) 规格 (http://www.w3.org/TR/xpath-datamodel) 内容如下:
[定义:每个实例 数据模型是一个序列。]。
[定义:序列是有序的 零个或多个项目的集合。] A 序列不能是 a 的成员 顺序。单个项目出现在 它自己被建模为一个序列 包含一项。序列是 在 2.5 序列中定义。
[定义:一个项目要么是一个节点 或原子值],
在 XPath API 的情况下 - XPathNodeIterator 是序列 而 XPathItem (XPathNavigator) 表示项目。
【讨论】:
我认为本次讨论的答案具有误导性。我认为 .NET 3.5 不支持大多数 XSL/T 2.0 功能(如果有的话)。
一个例子:
在 .NET 3.5 下调用 2.0 函数会给出以下错误消息:
'current-dateTime()' 是一个未知的 XSLT 函数。
【讨论】:
为了将来参考,这里有一个很好的关于在 .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) 在 XSLTs 命名空间声明中为自定义类提供自定义命名空间声明(在 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>
成员显示.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>
【讨论】:
我认为上面的答案是错误的。我找不到任何证据表明 Microsoft 支持 XSLT 2.0。 XSLT != XPath。
【讨论】:
是的,XPathNavigator 3.5 支持 XSLT 2.0。
http://msdn.microsoft.com/en-us/library/system.xml.xpath.xpathnavigator.aspx
“System.Xml.XPath 命名空间中的 XPathNavigator 类是一个抽象类,它将用于导航和编辑 XML 信息项的光标模型定义为 XQuery 1.0 和 XPath 2.0 数据模型的实例。”
【讨论】: