强制使用XSLT 2版本与XslCompiledTransform。

4

我有以下的 XSLT,我需要使用 XSLT 2.0 函数,例如 'format-date'。我该如何声明 XSL 样式表来使用 XSLTCompiledTransform 类(c#,.net 4.5)以使用版本2.0?

 <xsl:stylesheet version="2.0"
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xmlns="http://www.w3.org/TR/xhtml1/strict"
               xmlns:msxsl='urn:schemas-microsoft-com:xslt' 
               xmlns:var='urn:var' 
               xmlns:JS='urn:JS'
                >
  <xsl:output method="html"/>
  <xsl:variable name="n" select="1"/>
  <xsl:template match="/NewDataSet">
    <html>
      <head>
        <style>
          table{border-collapse:collapse;font-family:"Verdana";}
          table,td{border:1px solid black;color:black; background-color:white;font-family:"Verdana";}
          table,th{border:1px solid balck;background-color:black;color:white;font-family:"Verdana"; }
          .rt{color:red;font-family:"Verdana";}
          .nt{color:black;font-family:"Verdana";}
          .redb{color:yellow; background-color:red;font-family:"Verdana";}
          .greenb{color:white;background-color:green;font-family:"Verdana";}
          .blackb{color:white;background-color:black;font-family:"Verdana";}
        </style>
        <title>EDI validation Result </title>
      </head>
      <body>
        <p class="nt">
          EDI validation result  of the PO <span class="rt"><xsl:value-of select="info/pono"/></span>
          received from <xsl:value-of select="info/CustomerName"/>.
        </p>

        <table>
           <th class="blackb" >Position</th>
          <th class="blackb"> Item Code </th>
          <th class="blackb">UoM</th>
          <th class="blackb"> Ordered Qty .</th>
          <th class="blackb">Ship Request</th>
          <th class="blackb"> Net-Quoted </th>
          <th class="blackb"> Net-Catalog </th>
          <th class="blackb">Status</th>
          <xsl:for-each select="Table">
            <tr>
              <xsl:choose>
                <xsl:when test="Status !=''">
                  <xsl:value-of disable-output-escaping="yes" select="JS:IncBlines()"/>
                  <td class="redb"><xsl:value-of select="Position"/></td>
                  <td class="redb"><xsl:value-of select="ItemCode "/></td>
                  <td class="redb"><xsl:value-of select="UoM"/></td>
                  <td class="redb"><xsl:value-of select="QtyOrdered"/></td>
                  <td class="redb"><xsl:value-of select="format-date(RequiredBy,'D1o [MNn] [Y0001]')"/></td>
                  <td class="redb"><xsl:value-of select="PriceQuoted"/></td>
                  <td class="redb"><xsl:value-of select="Net"/></td>
                  <td class="redb"><xsl:value-of select="Status"/></td>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="JS:IncGlines()"/>

                  <td class="greenb"><xsl:value-of select="Position"/></td>
                  <td class="greenb"><xsl:value-of select="ItemCode"/></td>
                  <td class="greenb"><xsl:value-of select="UoM"/></td>
                  <td class="greenb"><xsl:value-of select="QtyOrdered"/></td>
                  <td class="greenb"><xsl:value-of select="format-date(RequiredBy,'D1o [MNn] [Y0001]')"/></td>


                  <td class="greenb"><xsl:value-of select="PriceQuoted"/></td>
                  <td class="greenb"><xsl:value-of select="Net"/></td>
                  <td class="greenb"><xsl:value-of select="Status"/>OK</td>

                 </xsl:otherwise>
                </xsl:choose>
            </tr>
          </xsl:for-each>
        </table>

        <xsl:if test="JS:GetBlines() &gt; 0"    >

          <p class="nt">

              The order validation has failed,

              The order will not be processesed as there are <xsl:value-of select ="JS:GetBlines()"/> lines in error.
              <p class="rt">

                The P.O is rejected as per agreed processing rules.


          </p>
          </p>

        </xsl:if>

        <xsl:if test="JS:GetBlines() &lt; 1">
          <p class="nt">
          The Order validated succesfully.
          Will e-mail Order Acknoledgement (non-edi) shortly.
          </p>
        </xsl:if>

      </body>
    </html>
  </xsl:template>
  <msxsl:script language='JScript' implements-prefix='JS'>

    <![CDATA[
    var j :int=0;
    var blines:int =0;
    var glines:int=0;
    function Inc(current)
    {j=j+current;

  return  j+current;
    }
    function IncBlines()
    {
     blines++;
    }
    function IncGlines()
    {
    glines++;
    }

    function GetBlines()
    {
    return blines;
    }
    function GetGlines()
    {
    return glines;
    }
]]>
  </msxsl:script>
</xsl:stylesheet>
3个回答

9
正如Martin所写,微软的处理器仅支持1.0版本——即使在2016年现在也是如此。我曾遇到过类似的问题(需要在我的XSLT中使用正则表达式),并通过“使用内联C#来完成工作”来解决它。
我的解决方案基于这个例子:XSLT Stylesheet Scripting Using <msxsl:script> (MSDN) 你需要为你的 xsl:stylesheet 节点添加一些内容。我的看起来像这样:
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt"
            xmlns:user="urn:my-scripts"
            exclude-result-prefixes="msxsl">

然后,您需要定义您的脚本。我的脚本大致如下:

<!-- Script to check for URLs in values -->
<msxsl:script language="C#" implements-prefix="user">
    <![CDATA[
      public string ExtractUrl(string str)
      {
          return Regex.Match(str, @"(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*))").Value;
      }
    ]]>
</msxsl:script>

此后,我能够在我的XSLT中调用这个函数:

<xsl:variable name="extractedUrl" select="user:ExtractUrl(.)"></xsl:variable>

在教程页面上没有提到,但是在我在服务器上处理XSLT时,我还需要创建一个XsltSettings对象来启用脚本执行:

XsltSettings settings = new XsltSettings(false, true); // enable script execution
XsltCompiledTransform transform = new XslCompiledTransform();
transform.Load("template.xsl", settings, new XmlUrlResolver());

当然,考虑安全性——如果您允许执行任意的C#脚本,请确保您的XSLT文件仅包含受信任和/或经过消毒的输入。

8

微软的XslCompiledTransform是一个XSLT 1.0处理器。要在.NET中使用XSLT 2.0,您有两个第三方选项,分别是来自http://saxon.sourceforge.net/ 的Saxon 9的.NET版本或XmlPrime。Saxon有一个开源版本HE和两个商业版本PE和EE,XmlPrime用于商业用途需要许可证。


1
显然,msxsl ns提供了一组扩展函数,包括用于xslt 1.0处理器的format-date()函数。 - TonyP

3
作为已批准答案的补充,这里是对@TonyP的评论使用Microsoft的format-date进行扩展的内容。
关于format-date的MSDN文档: https://msdn.microsoft.com/en-us/library/ms256099%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 示例
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="xsl msxsl"
>

<!-- ... --->
<td class="redb"><xsl:value-of select="msxsl:format-date(RequiredBy,'d MMMM yyyy')"/></td>
<!-- ... --->

NB: 微软的日期格式选项远不及XSLT 2.0中可用的丰富(请参阅文档); 因此,我认为d MMMM yyyy格式是最接近您要求的格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接