使用 Delphi XE8 的 XSLT 转换的替代方案

Alternatives for XSLT transformations with Delphi XE8

我正在尝试使用 Delphi XE8 执行 XSLT 转换,但 运行 遇到了问题。我的 XSL 文件使用 import 语句引用外部 XSL 文件,其 href 属性具有相对路径。转换失败并出现错误 "Named template 'skrivUtDate' does not appear in the stylesheet." 定义 'skrivUtDate' 位于外部 XSL 文件中。定义如下所示:

<xsl:template name="skrivUtDate">
    <xsl:param name="oppgittTid"/>
    <xsl:if test="string-length($oppgittTid)!=0">
        <xsl:value-of select="substring($oppgittTid,9,2)"/>.<xsl:value-of select="substring($oppgittTid,6,2)"/>.<xsl:value-of select="substring($oppgittTid,3,2)"/>
    </xsl:if>
</xsl:template>

我已将外部 XSL 文件放在适当的目录中(相对于原始 XSL 文件),但我得到了同样的错误(我也尝试了该外部文件的所有其他可能的目录,但是 none已经工作)。但是,我可以使用 EditX XML 编辑器执行转换,所以我不认为 XSL 无效(请注意,这个 XSL 文件是由第三方提供的,显然它被一些人成功使用Delphi 以外的开发平台)。

这是 XSL 文件的开头部分:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:ref="http://www.kith.no/xmlstds/henvisning/2012-02-15" 
  xmlns:xhtml="http://www.w3.org/1999/xhtml" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:po="http://www.kith.no/xmlstds/po/poKomponent/2009-06-30" 
  xmlns:fk1="http://www.kith.no/xmlstds/felleskomponent1" 
  exclude-result-prefixes="ref xhtml po fk1">
    <xsl:import href="../../Felleskomponenter/funksjoner.xsl"/>

是的,funksjoner.xsl 文件位于名为 Felleskomponenter 的目录中。

我非常简单的测试使用了类似于以下伪代码的内容:

var
  XML : IXMLDocument;
  XSL : IXMLDocument;
  s: WideString;
begin
  XML := TXMLDocument.Create(self);
  XML.FileName := 'C:\somepath\some.xml';
  XML.Active := True;
  XSL := TXMLDocument.Create(Self);
  XSL.FileName := 'C:\someotherpath\somefile.xsl';
  XSL.Active := True;
  XML.DocumentElement.TransformNode(XSL.DocumentElement, s);

我知道 Delphi XE7 开始与 Omni XML DOM 以及 ADOM 一起发货,但 [=33= 显然没有这些] XE8。我希望使用不同的文档对象模型可以解决这个问题。

XML 非常复杂,XSL 也是如此。

是否有人对使用 Delphi XE8 执行 XSLT 转换的替代方法有任何建议?

要使 XSLT 在 Delphi 中正常工作,您需要使用 MSXML 加载 XML 和 XSL 文件。这个post给出了一个n example on how to use MSXML with DelphiTransformNode 在后台使用 MSXML。

以下内容应该有效(采用 from here,片段不完整):

var
  xmlEmployees, xslStyle : IXMLDOMDocument;
begin
  xmlEmployees := CoDOMDocument.Create;
  xslStyle     := CoDOMDocument.Create;
  xmlEmployees.load('employees.xml');
  xslStyle.load('empuksna.xsl');
  result := xmlEmployees.transformNode(xslStyle);
end; 

同样,如果您要通过字符串加载 XML 和 XSL,原始位置就会丢失。大多数处理器都支持设置基本 uri,但看起来 IXSLProcessor 没有这样的选项。


您还要求替代方案。 DIXML 支持 libxslt,它在很多方面优于 MSXML(但不优于 .NET 的 XSLT,如果您喜欢与 .NET 互操作,这是另一种选择)。 The package of DIXML 在演示文件夹中附带了一堆演示和示例。

如果您可以切换到 .NET,this (rather old) DrDobb's article shows how to do XSLT with .NET and Delphi 并且还显示了另一种转换方法(尽管它假设 Delphi 7,但不确定它是否仍然适用)。

现在可能是多余的,但我发现解决导入和包含路径问题的最简单方法是使用绝对路径。

如果使用相对路径,它是相对于 msxml.exe 的安装目录,而不是你的 exe 或根 xsl。在不同服务器之间切换时会出现问题。

如果您需要本机和跨平台的解决方案:OXml 提供完全用 Delphi/Pascal 编写的 XSLT 引擎。不过,它是一种商业产品。 (我是 OXml 的作者。)