【问题标题】:Are .NET 3.5 XPath classes and methods XSLT 2.0 compatible?.NET 3.5 XPath 类和方法是否与 XSLT 2.0 兼容?
【发布时间】:2010-09-10 18:40:48
【问题描述】:

我想在使用 match 函数选择元素时使用正则表达式。我不希望使用外部库(例如 saxon)来执行此操作。

【问题讨论】:

    标签: xml xslt .net-3.5 xpath


    【解决方案1】:

    XSLT 2.0 中的某些内容在内置库中不受支持(在 mono 邮件列表中对此进行了讨论,但我再也找不到相关信息了)。但大多数人从不遇到不受支持的极端情况。

    另一种选择是查看开源http://saxon.sourceforge.net/,它对 2.0 有很好的支持。

    编辑(AB):上述接受的答案可能会令人困惑。根本不支持,.NET 中的任何 XPath 2.0 或 XSLT 2.0 函数都有 no plans in that direction

    【讨论】:

    • “我不希望使用外部库(例如 saxon)来执行此操作。”
    • 角落案例? XSLT 2.0 是对 1.0 规范的完全重写和非常广泛的扩展。目前没有任何对 .NET 中 XSLT 2.0 或 XPath 2.0 的新功能的支持,也没有任何计划:stackoverflow.com/questions/1525299/xpath-and-xslt-2-0-for-net
    • 我想我在这方面得到了赏金,它会自动选择票数最高的答案。有了 Abel 的加入,现在这是一个不错的选择。
    【解决方案2】:

    在讨论 .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) 表示项目。

    【讨论】:

    • 优秀的答案,比实际答案正确得多;-)。我一直在寻找有关 XDM 支持(和使用?)的官方文档,但找不到。 Kadluczka 可能认识一个吗?
    • 先生。 Kadluczka 不推荐任何此类文件。如果您有任何具体问题,我建议您通过他们的博客blogs.msdn.com/xmlteam 联系 Microsoft XML 团队。
    【解决方案3】:

    我认为本次讨论的答案具有误导性。我认为 .NET 3.5 不支持大多数 XSL/T 2.0 功能(如果有的话)。

    一个例子

    在 .NET 3.5 下调用 2.0 函数会给出以下错误消息:

    'current-dateTime()' 是一个未知的 XSLT 函数。

    【讨论】:

    • 你是完全正确的。根本不支持 XSLT 2.0。答案确实具有误导性。我在该答案中添加了注释。
    【解决方案4】:

    为了将来参考,这里有一个很好的关于在 .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>        
    

    【讨论】:

    • +1 篇优秀的文章以及在 .NET 中扩展 XSLT 1.0 的解释。
    • @abel 去访问我链接的网站,给他们一些爱。我从他们那里偷走了所有东西。
    【解决方案5】:

    我认为上面的答案是错误的。我找不到任何证据表明 Microsoft 支持 XSLT 2.0。 XSLT != XPath。

    【讨论】:

    【解决方案6】:

    是的,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 数据模型的实例。”

    【讨论】:

    • 那为什么matches函数不能识别呢?
    • 我不知道;它已记录在案。 msdn.microsoft.com/en-us/library/…
    • XSLT 与 XPath 或 XQuery 不同,因此它确实不支持 XSLT 2.0(它有一些功能,但不是很多。)
    • @Scott:恐怕连“几件事”都没有。不支持 XPath 2.0 或 XSLT 2.0。他们已经宣布了一项实施,但后来又撤回了。
    猜你喜欢
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2020-10-07
    • 1970-01-01
    • 2011-02-18
    • 2010-12-04
    • 2010-11-30
    相关资源
    最近更新 更多