我有一个XSL文件,除了在Delphi中,它在我尝试过的每个地方都可以正常工作。适用于Web解析器(例如https://xslttest.appspot.com/),并且在使用Microsoft的msxsl.exe
时适用。
但是,在Delphi 10.2中调用transformNode()
时,以下代码给出了异常:
样式表不包含文档元素。样式表可能为空,或者可能不是格式正确的XML文档。
据我了解,这应该使用msxsl
使用的相同MSXML?
uses
Winapi.MSXML;
procedure TForm1.Button1Click(Sender: TObject);
var
transformstring: string;
xmldoc, xsldoc: IXMLDOMDocument3;
begin
xmldoc := CoDOMDocument60.Create;
xsldoc := CoDOMDocument60.Create;
xmldoc.load('C:\Temp\Data.xml');
xsldoc.load('C:\Temp\Stylesheet.xsl');
xsldoc.setProperty('AllowXsltScript', True);
transformstring := xmldoc.transformNode(xsldoc);
end;
XSL文件是(已最小化):
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="D2DSeverityFilter">^Caution^Minor^Moderate^Severe^</xsl:param>
<xsl:param name="D2HSeverityFilter">^Extreme Caution^Contraindication^Contraindicated^</xsl:param>
<xsl:param name="DocumentationFilter">^Not Established^Limited^Good^Well Established^</xsl:param>
<xsl:output method="html" omit-xml-declaration="yes"/>
</xsl:stylesheet>
输入数据似乎不相关,但为完整起见,此空文件将起作用:
<?xml version="1.0" encoding="windows-1252"?>
<Result ></Result>
下面是固定代码,包括需要设置的其他属性。
uses
Winapi.MSXML;
procedure TForm1.Button1Click(Sender: TObject);
var
transformstring: string;
xmldoc, xsldoc: IXMLDOMDocument3;
begin
xmldoc := CoDOMDocument60.Create;
xsldoc := CoDOMDocument60.Create;
xmldoc.load('C:\Temp\Data.xml');
xsldoc.setProperty('AllowXsltScript', True);
xsldoc.setProperty('ProhibitDTD', False);
xsldoc.setProperty('ValidateOnParse', False);
xsldoc.load('C:\Temp\Stylesheet.xsl');
transformstring := xmldoc.transformNode(xsldoc);
end;
答案 0 :(得分:0)
MSXML有不同版本,您的Delphi代码似乎尝试使用MSXML6。出于安全原因,我认为它具有各种属性的不同默认设置,其中之一与DTD相关。因此,鉴于您的XSLT示例尝试使用DTD,我认为您需要明确允许它,请参见https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms762632%28v%3dvs.85%29。
因此,我认为将xsldoc.setProperty('ProhibitDTD', False)
调用设置为load
之前应该会有所帮助。
此外,正如我们在评论部分所梳理的那样,DTD与MSXML 6默认设置的结合使用试图验证通过load
调用解析的文档,这会阻止您的样式表被处理。 DTD片段显然没有为XSLT样式表指定完整的语法。因此,您需要设置
xsldoc.setProperty('ValidateOnParse', False)
也是。