1

我正在尝试使用 Delphi XE8 执行 XSLT 转换并遇到问题。我的 XSL 文件使用其 href 属性具有相对路径的 import 语句引用外部 XSL 文件。转换失败并出现错误“命名模板 'skrivUtDate' 未出现在样式表中。” 定义“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 文件),但我得到了相同的错误(我还尝试了该外部文件的所有其他可能的目录,但没有一个有效)。但是,我可以使用 EditX XML Editor 执行转换,所以我不认为 XSL 是无效的(注意这个 XSL 文件是由第三方提供的,显然它被一些使用开发平台以外的人成功使用德尔福)。

这是 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 一起发布,但 Delphi XE8 显然没有这些。我希望使用不同的文档对象模型可以解决这个问题。

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

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

4

3 回答 3

3

要使 XSLT 在 Delphi 中正常工作,您需要使用 MSXML 来加载 XML 和 XSL 文件。这篇文章给出了一个关于如何在 Delphi 中使用 MSXML的示例。TransformNode引擎盖下使用 MSXML 。

以下内容应该可以工作(取自此处,不完整的片段):

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 互操作,它是另一种选择)。DIXML 的软件包在 demo 文件夹中附带了一堆演示和示例。

如果您可以切换到 .NET,这篇(相当旧的)DrDobb 的文章展示了如何使用 .NET 和 Delphi 进行 XSLT,并且还展示了另一种转换的替代方案(尽管它假定 Delphi 7,但不确定它是否仍然适用)。

于 2015-09-21T16:06:51.910 回答
0

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

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

于 2020-07-17T05:02:23.827 回答
0

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

于 2020-07-27T05:07:34.043 回答