UWP:允许在 WebView 中对本地内容进行 XSL 转换
UWP: allow XSL transformation in a WebView for local content
我想在 WebView
上显示本地 XML 文件。 XML 文件引用本地 XSL 文件(在同一文件夹中)。但是未应用样式表,其原因似乎是安全问题。
如果我在 Edge 的控制台中打开文件,我得到
XSLT8690: The system cannot locate the object specified.
是否有可能允许对本地文件进行 XSL 转换(例如 here)?如何显示引用样式表的本地 XML 文件?
如果您的 XML 和 XSL 文件不在应用程序的资产文件夹中,则设置 WebView.Navigate method or WebView.Source property to the XML file will not work. To solve this issue, we can use XsltProcessor class to transform xml according to the style sheet declaration specified in xslt file first and then using WebView.NavigateToString 方法以加载转换后的 HTML 内容。
例如:
var xmlFile = await ApplicationData.Current.LocalCacheFolder.GetFileAsync("test.xml");
var xsltFile = await ApplicationData.Current.LocalCacheFolder.GetFileAsync("test.xsl");
var doc = await Windows.Data.Xml.Dom.XmlDocument.LoadFromFileAsync(xmlFile);
var xsltDoc = await Windows.Data.Xml.Dom.XmlDocument.LoadFromFileAsync(xsltFile);
// Transform xml according to the style sheet declaration specified in xslt file
var xsltProcessor = new Windows.Data.Xml.Xsl.XsltProcessor(xsltDoc);
var transformedStr = xsltProcessor.TransformToString(doc);
//MyWebView is the WebView control in XAML
MyWebView.NavigateToString(transformedStr);
更新:
I get Error HRESULT E_FAIL has been returned from a call to a COM component. at Windows.Data.Xml.Xsl.XsltProcessor.TransformToString(IXmlNode inputNode).
这里的问题是,在您的示例的 XSL 文件中,它使用了 XSLT document()
函数。但是出于安全原因,在 UWP 中禁止执行 document()
函数。所以你在执行 XsltProcessor.TransformToString
方法时得到错误。
对于经典的 .NET Framework 应用程序,我们可以设置 XsltSettings.EnableDocumentFunction Property to enable support for the XSLT document()
function. However there is no such class or property in UWP. You are welcome to submit a request for this feature through UserVoice。
对于您的特定 XSL 文件,它只在两个地方使用了 document()
函数:
<xsl:if test="$useexternalcss=1">
<style type="text/css" media="screen">
<xsl:value-of select="document($externalcssname)" />
</style>
</xsl:if>
...
<p class="subtitle_create">
<xsl:text>Angezeigt mit </xsl:text>
<xsl:value-of select="document('')/xsl:stylesheet/@id" />
</p>
首先,由于没有使用外部css,所以document()
函数不会执行。我们可以忽略它或者肯定地注释掉它。其次,document()
函数用于获取 stylesheet
的 id
,即 "ELGA_Referenzstylesheet_1.04.009.1",我认为这值是一个常数。如果样式表没有改变,它就不会改变。所以我想你可以像下面这样改变它:
<p class="subtitle_create">
<xsl:text>Angezeigt mit </xsl:text>
<xsl:text>ELGA_Referenzstylesheet_1.04.009.1</xsl:text>
</p>
之后可以用XsltProcessor.TransformToString
方法重试,应该可以的。
我想到的可能选项:
- 使用其他浏览器
- 使用本地网络服务器
- 将 xml 和 xsl 文件放到网络服务器上并仅访问 URL(让网络服务器进行转换)
- 通过 Javascript (xslt.js, Saxon-CE, Magic XML, Google ajaxslt, Sarissa or even a custom solution)
在浏览器中使用 XSLT 转换
- 使用Libxslt 库
浏览器方式的缺点是,所有库都过时了,现有的不支持转换的所有功能。可以找到实现 here and here. There are also some jQuery wrapper available (see [1], [2] or [3]).
还有一个 feature request 用于 webview。
,无效。此处显示一个空白的白色页面。但如果您使用资产文件夹中的文件(在编译时包含该文件),它就可以工作。
我想在 WebView
上显示本地 XML 文件。 XML 文件引用本地 XSL 文件(在同一文件夹中)。但是未应用样式表,其原因似乎是安全问题。
如果我在 Edge 的控制台中打开文件,我得到
XSLT8690: The system cannot locate the object specified.
是否有可能允许对本地文件进行 XSL 转换(例如 here)?如何显示引用样式表的本地 XML 文件?
如果您的 XML 和 XSL 文件不在应用程序的资产文件夹中,则设置 WebView.Navigate method or WebView.Source property to the XML file will not work. To solve this issue, we can use XsltProcessor class to transform xml according to the style sheet declaration specified in xslt file first and then using WebView.NavigateToString 方法以加载转换后的 HTML 内容。
例如:
var xmlFile = await ApplicationData.Current.LocalCacheFolder.GetFileAsync("test.xml");
var xsltFile = await ApplicationData.Current.LocalCacheFolder.GetFileAsync("test.xsl");
var doc = await Windows.Data.Xml.Dom.XmlDocument.LoadFromFileAsync(xmlFile);
var xsltDoc = await Windows.Data.Xml.Dom.XmlDocument.LoadFromFileAsync(xsltFile);
// Transform xml according to the style sheet declaration specified in xslt file
var xsltProcessor = new Windows.Data.Xml.Xsl.XsltProcessor(xsltDoc);
var transformedStr = xsltProcessor.TransformToString(doc);
//MyWebView is the WebView control in XAML
MyWebView.NavigateToString(transformedStr);
更新:
I get Error HRESULT E_FAIL has been returned from a call to a COM component. at Windows.Data.Xml.Xsl.XsltProcessor.TransformToString(IXmlNode inputNode).
这里的问题是,在您的示例的 XSL 文件中,它使用了 XSLT document()
函数。但是出于安全原因,在 UWP 中禁止执行 document()
函数。所以你在执行 XsltProcessor.TransformToString
方法时得到错误。
对于经典的 .NET Framework 应用程序,我们可以设置 XsltSettings.EnableDocumentFunction Property to enable support for the XSLT document()
function. However there is no such class or property in UWP. You are welcome to submit a request for this feature through UserVoice。
对于您的特定 XSL 文件,它只在两个地方使用了 document()
函数:
<xsl:if test="$useexternalcss=1">
<style type="text/css" media="screen">
<xsl:value-of select="document($externalcssname)" />
</style>
</xsl:if>
...
<p class="subtitle_create">
<xsl:text>Angezeigt mit </xsl:text>
<xsl:value-of select="document('')/xsl:stylesheet/@id" />
</p>
首先,由于没有使用外部css,所以document()
函数不会执行。我们可以忽略它或者肯定地注释掉它。其次,document()
函数用于获取 stylesheet
的 id
,即 "ELGA_Referenzstylesheet_1.04.009.1",我认为这值是一个常数。如果样式表没有改变,它就不会改变。所以我想你可以像下面这样改变它:
<p class="subtitle_create">
<xsl:text>Angezeigt mit </xsl:text>
<xsl:text>ELGA_Referenzstylesheet_1.04.009.1</xsl:text>
</p>
之后可以用XsltProcessor.TransformToString
方法重试,应该可以的。
我想到的可能选项:
- 使用其他浏览器
- 使用本地网络服务器
- 将 xml 和 xsl 文件放到网络服务器上并仅访问 URL(让网络服务器进行转换)
- 通过 Javascript (xslt.js, Saxon-CE, Magic XML, Google ajaxslt, Sarissa or even a custom solution) 在浏览器中使用 XSLT 转换
- 使用Libxslt 库
浏览器方式的缺点是,所有库都过时了,现有的不支持转换的所有功能。可以找到实现 here and here. There are also some jQuery wrapper available (see [1], [2] or [3]).
还有一个 feature request 用于 webview。