如何使用 WebView2 使用 XSL 转换显示 XML 内容?

问题描述

我正在使用 .Net Core 在 WPF 中创建应用程序,并且需要显示创作的 XML 内容。我们使用其他软件将 xml 转换为 html 以便在线托管。但是,在创作时,我需要能够看到使用 xsl 文件转换的本地 XML 内容的预览。我正在使用 Linq to XML。

我首先在 WebView2 中创建了一个 TabItem 控件。使用预发布版本 1.0.790,我尝试使用 SetVirtualHostNametoFolderMapping 但没有成功。我一开始只是尝试使用示例代码的复制粘贴打开一个通用的 html 文件,但只收到一条消息,说无法解析 appassets.example 的 IP。我仔细检查了文件夹的位置,以及该文件夹中的文件

我的下一次尝试是利用 NavigatetoString 并发送 xml。这有几个问题。第一个是任何 XProcessingInstruction get 都转换为评论,我认为这是一项安全功能?没有它,我所看到的只是内部 xml 内容。 xml 更改自:

<?xml-stylesheet type="text/xsl" href="Template-xsl.xsl"?>

进入评论

<!--?xml-stylesheet type="text/xsl" href="Template-xsl.xsl"?-->

一个不相关的问题是,如果我添加一个 InternalSubset,webview 无法识别关闭]> 我不确定这是否是一个 WebView 问题,所以我在 Notepad++ 中检查了它那里看起来是同样的问题。我试过删除空格和换行符,但没有任何改变。第一个实体似乎显示正常,但下一行总是不同的颜色,这让我相信它以某种方式将第一个实体的结尾读取为结尾 DocType。 DocType 的 XML 是:

<!DOCTYPE dmodule [
   <!ENTITY svg-test SYstem "svg-test.svg" NDATA svg >
   <!ENTITY svg-test1 SYstem "svg-test1.svg" NDATA svg >
]>

我开始只是创建一个字符串并更新 InternalSubset。然后我尝试创建一个新的文档类型并插入与上述结果相同的文档类型。

string ent = Environment.NewLine;
                foreach (SVG s in sVGs)
                {
                    string en = "   <!ENTITY " + s.GraphicInfoEntityIdent + " SYstem \u0022" + s.FileName + "\u0022 NDATA svg >" + Environment.NewLine;
                    ent += en;
                }
                var doctype = new XDocumentType("dmodule",null,ent);
                xDoc.AddFirst(doctype);

我错过了什么,这是最好的方法吗?

编辑 1:我假设浏览器只会处理转换,但显然情况并非如此。根据 Martin 的建议,我返回并创建了一种新方法来在将 xml 传递给 Webview 之前对其进行转换。这似乎有效,但我不断收到 xslt 编译错误。它没有给我任何原因的指示,所以我开始破坏 xslt 脚本并找到了罪魁祸首。我需要弄清楚如何让编译工作,因为没有它转换将无法完全工作,但这是另一个问题。浏览器将显示转换后的 xml 内容

解决方法

如果我在关注,你想

  • 找到本地 XML 文件和本地 XSL 文件
  • 用 XSL 将 XML 转换为 HTML 并显示 HTML 结果

我从来没有在浏览器转换方面走运过,所以我有一个不同的解决方案。在您的 XPF 程序中运行转换并将 HTML 结果发送给浏览器。

  1. 使用您的 WPF 程序加载 XML、XSL 并转换为 HTML。由于 WPF 程序是“本地的”,因此它可以完全查看本地文件。
  2. 在您的 WebView2 控件中加载一个特殊的网页。将您的 HTML 发布到 WebView2 窗口。下面的示例(注意脚本)从 XPF 程序中捕获消息。
  3. 在您的 WPF 程序中,将第 1 步中的 HTML 发布到特殊网页。
  4. 最后,.JS 捕获消息 (HTML),并用它更新页面。

这是一个特殊的网页,它监听来自 XPF 程序的 HTML。

<html>
    <head>
    </head>
    <body>
        <div id='xformhtml'/>
    </body>

    <script type='text/javascript'>

    let xformDiv = document.querySelector( "#xformhtml );

    if( window.chrome.webview ) {
        window.chrome.webview.addEventListener( 'message',event => {
            xformDiv.innerHTML = event.data;
        });
    } else {
        xformDiv.innerHTML = "<h2>Sorry webview communication not supported.</h2>"
    }
    </script>
</html>

此链接显示了如何与示例页面进行通信。

https://github.com/MicrosoftEdge/WebView2Feedback/issues/247