【问题标题】:Alternatives for XSLT transformations with Delphi XE8使用 Delphi XE8 进行 XSLT 转换的替代方案
【发布时间】:2015-12-18 07:06:48
【问题描述】:

我正在尝试使用 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 转换的替代方法有任何建议?

【问题讨论】:

  • MSXML 似乎无法处理具有导入文件相对路径的几层 元素(有 3 个级别,第三级有 2 个导入,尽管这些文件是在与它们被导入的文件相同的目录中)。 DIXML 能够正确解析 XSL 文件,并且易于使用,但转换返回了 AnsiString,导致一些 Unicode 字符被破坏。我在这里发布了一个关于 DIXML 的新问题:stackoverflow.com/questions/32760579/…

标签: xml delphi xslt delphi-xe8 txmldocument


【解决方案1】:

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

以下内容应该可以工作(采取from here,不完整的sn-p):

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 在 demo 文件夹中附带了一堆演示和示例。

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

【讨论】:

  • 感谢您的慷慨投入。我还没有这个工作 - 我仍然在 Delphi 中遇到错误,即使 EditX XML 编辑器可以执行转换。我会报告我的进度。
  • @CaryJensen,如果您使用的是现代 Windows 机器,则安装的 MSXML 版本可能不是您尝试加载的版本。如果COM操作失败,请尝试download MSXML(通常是3.0或6.0或两者,其他版本有问题)
  • @CaryJensen,您可以使用XmlVersion.exe or Versions.exe检查已安装的版本
  • 仍然没有喜悦。仅供参考:我在 IXMLDOMDocument 实例上调用 LoadXML 方法来加载 XML。我得到的错误是“样式表不包含文档元素。样式表可能是空的,或者它可能不是格式正确的 XML 文档。”有一个文档元素,它看起来格式正确。顺便说一句,如果我只调用 Load 方法,我会收到一条错误消息“系统找不到指定的路径。”
  • @cary,我假设您使用外部命令行处理器测试了样式表并发现它是正确的?您能否发布您在问题中尝试的确切、最少的代码?
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2015-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多