0

I want to display a local XML file on a WebView. The XML file references a local XSL file (in the same folder). But the stylesheet is not applied and the reason for this seems to be security concerns.

If I open the file in the console of Edge I get

XSLT8690: The system cannot locate the object specified.

Is there a possibility to allow the XSL transformation of a local file (e.g. like here)? How can I display a local XML file, which references a stylesheet?

Community
  • 1
  • 1
testing
  • 19,681
  • 50
  • 236
  • 417
  • Where did you put the XML and XSL file? I put them under application's assets folder and it works well. – Jay Zuo Oct 25 '16 at 02:57
  • Yes, the assets folder does work. I want to put it in any other folder e.g. `TempState`, `LocalCache` and so on. – testing Oct 25 '16 at 08:00

2 Answers2

1

If your XML and XSL file are not in application's assets folder, then setting the 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 method to load the transformed HTML content.

For example:

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);

Update:

I get Error HRESULT E_FAIL has been returned from a call to a COM component. at Windows.Data.Xml.Xsl.XsltProcessor.TransformToString(IXmlNod‌​e inputNode).

The problem here is that in your example's XSL file, it is using XSLT document() function. However for security reasons, execution of the document() function was prohibited in UWP. So you get the error when executing XsltProcessor.TransformToString method.

For classic .NET Framework apps, we can set 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.

And for your specific XSL file, it only used document() function in two place:

<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>

For the first place, as it didn't use external css, so the document() function won't execute. We can ignore it or comment out it for sure. And in the second place, document() function is used to get the stylesheet's id which is "ELGA_Referenzstylesheet_1.04.009.1" and I think this value is a constant. It won't change if the stylesheet didn't change. So I think you can change it like following:

<p class="subtitle_create">
  <xsl:text>Angezeigt mit </xsl:text>
  <xsl:text>ELGA_Referenzstylesheet_1.04.009.1</xsl:text>
</p>

After this, you can retry with XsltProcessor.TransformToString method, it should be able to work.

Jay Zuo
  • 15,653
  • 2
  • 25
  • 49
  • 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)*. – testing Oct 31 '16 at 17:27
  • @testing What's the xml and xsl file you are using? I'm testing with [the code here](http://www.w3schools.com/xml/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog) and it works well. – Jay Zuo Nov 01 '16 at 01:49
  • Take *ELGA-023-Entlassungsbrief_aerztlich_EIS-FullSupport.xml* from [these examples](https://www.elga.gv.at/fileadmin/user_upload/Dokumente_PDF_MP4/CDA/Beispieldokumente_2.06.1/Beispieldokumente_2.06.1.zip). – testing Nov 02 '16 at 12:00
  • @testing Yeah I can reproduce your issue. The problem here is related to the XSLT document() function. Please check my updated answer. – Jay Zuo Nov 03 '16 at 08:22
  • 1
    I'm glad you figured it out, what the reason is. The linked xml document is only an example, demonstrating all of the features a document of this type can support, according to the norm. There are different types of xml documents and all of them should be supported. That means in real use cases I don't know, when the `document()` function is used and when not. I can filter through known cases as you demonstrated this. But that wouldn't be a robust solution. My best bet would be to use your approach with the `XsltProcessor` and use for example the Javascript fallback. Or any other idea? – testing Nov 03 '16 at 09:58
  • 1
    I've filled a [feature request](https://wpdev.uservoice.com/forums/110705-universal-windows-platform/suggestions/16933771-enabledocumentfunction-property-to-allow-document) to speed up the process. This would be the solution I need in this case! – testing Nov 03 '16 at 10:43
0

Possible options, which comes to my mind:

The disadvantage of the browser method is, that all libraries are outdated and the existing ones do not support all features for the transformation. Implementations can be found here and here. There are also some jQuery wrapper available (see [1], [2] or [3]).

There is also a feature request for the webview.

Copying the xml file to the asset folder, doesn't work. A blank, white page is displayed here. But it works, if you use a file from the asset folder, which you include before compile time.

Community
  • 1
  • 1
testing
  • 19,681
  • 50
  • 236
  • 417