XSLT unparsed-text() 的URL解析已发布
我在一个.NET应用中使用Saxon-HE 10.9.0进行转换,使用一个带有unparsed-text() 的XSLT,将JavaScript内联到输出的HTML文件中,例如:
<xsl:value-of select="unparsed-text('https://code.jquery.com/jquery-3.5.1.min.js')"/><xsl:text>
当我在XMLSpy中运行XSLT时,输出如预期生成。然而,在使用Saxon-HE 10.9.0的 NuGet库在.NET程序中运行时,我遇到了以下错误:
Cannot convert absolute URI https://code.jquery.com/jquery-3.5.1.min.js to URL at Saxon.Api.Xslt30Transformer.ApplyTemplates(Stream input, XmlDestination destination)
我已经了解到这可能与IKVM问题相关,并向项目添加了以下App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ikvm:https.protocols" value="TLSv1,TLSv1.1,TLSv1.2" />
</appSettings>
<connectionStrings>
<add key="ikvm:https.protocols" value="TLSv1,TLSv1.1,TLSv1.2" />
</connectionStrings>
</configuration>
然而,问题仍然存在。
解决方案
我已将当前版本的Saxon HE,即Saxon HE 12,交叉编译为.NET,使用一个较新的IKVM版本,该版本可能不会再有此类问题,因为它使用了更新的OpenJDK,NuGet包是 SaxonHE12s9apiExtensions,下面是一些示例代码
using System;
using System.IO;
using net.liberty_development.SaxonHE12s9apiExtensions;
using net.sf.saxon.s9api;
namespace SaxonHE12TestUnparsedTextHTTPAccess2
{
internal class Program
{
static void Main(string[] args)
{
var processor = new Processor();
var xsltCompiler = processor.newXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new FileInfo("sheet1.xsl"));
var xslt30Transformer = xsltExecutable.load30();
xslt30Transformer.callTemplate(null, processor.NewSerializer(Console.Out));
}
}
}
.NET/VS的项目文件需要采用现代项目风格,因为现代IKVM只能在这种项目风格下工作:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net481</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SaxonHE12s9apiExtensions" Version="12.9.10" />
</ItemGroup>
<ItemGroup>
<None Update="sheet1.xsl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
例如,sheet1.xsl可以无需问题地访问你的HTTPS URL,例如:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:template name="xsl:initial-template">
<xsl:value-of select="unparsed-text('https://code.jquery.com/jquery-3.5.1.min.js')"/>
</xsl:template>
</xsl:stylesheet>
如果你想继续使用Saxon HE 10.9与 Saxon.Api,我也将Saxon HE 10与 IKVM一起交叉编译到.NET,主要是.NET(Core)。我今天还将这些包更新为也可以交叉编译到.NET 4.8.1(这是.NET框架的最新版本),NuGet包是 SaxonHE10Net31Api,它使用了最新版的IKVM和 IKVM.Maven.Sdk,与上文的Saxon HE 12示例一样,你需要使用现代的.NET/VS项目形式,因此一个示例将是(在此示例中同时目标.NET框架和最新版.NET 10,当然你只能将.NET框架定位到4.8.1,例如使用 <TargetFramework>net481</TargetFramework>)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0;net481</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IKVM.Maven.Sdk" Version="1.11.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SaxonHE10Net31Api" Version="10.9.21" />
<MavenReference Include="net.sf.saxon:Saxon-HE" Version="10.9" />
</ItemGroup>
<ItemGroup>
<None Update="sheet1.xsl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
C#代码如下
using System;
using System.IO;
using Saxon.Api;
namespace SaxonHE10UnparsedTextHTTPSAccessTest1
{
internal class Program
{
static void Main(string[] args)
{
var processor = new Processor();
var xsltCompiler = processor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new Uri(Path.Combine(Environment.CurrentDirectory, "sheet1.xsl")));
var xslt30Transformer = xsltExecutable.Load30();
xslt30Transformer.CallTemplate(null, processor.NewSerializer(Console.Out));
}
}
}
在Windows 11的 .NET 4.8.1下,这段代码也同样能正常运行。