0

I’m making a UWP app with Visual Studio 2022. A user can convert .xml and .xsl into a .pdf by drag-and-dropping them into an app.

The problem is that Aspose can’t read xml neither xsl. They try to access its path obtained from drag-and-drop. I think an app can access files and directories as long as they are selected with a filepicker or drag-and-drop, so I'm a little bit confused.

Any help is greatly appreciated!

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace XML2PDF
{
    public sealed partial class MainPage : Page
    {
        string xmlPath;
        string xslPath;
        public MainPage()
        {
            this.InitializeComponent();
            xmlPath = "";
            xslPath = "";
        }

        private void BackgroundGrid_DragEnter(object sender, DragEventArgs e)
        {
            e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move;
        }

        private async void BackgroundGrid_Drop(object sender, DragEventArgs e)
        {
            if (e.DataView.Contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.StorageItems))
            {
                var items = await e.DataView.GetStorageItemsAsync();
                var filePaths = items.Select(x => x.Path).ToList();
                foreach (var p in filePaths)
                {
                    if (p.EndsWith(".xml"))
                    {
                        xmlPath = p;
                        continue;
                    }
                    if (p.EndsWith(".xsl"))
                    {
                        xslPath = p;
                        continue;
                    }
                }
            }
            // TODO: check if xmlPath and xslPath aren't empty
            this.ConvertXML2PDF(xmlPath, xslPath);
        }

        private async void ConvertXML2PDF(string xmlPath, string xslPath)
        {
            Aspose.Pdf.Document pdf = new Aspose.Pdf.Document();
            string pdfPath = xmlPath.Replace(".xml", "pdf");
            try
            {
                pdf.BindXml(xmlPath, xslPath);
                // System.UnauthorizedAccessException: 'Access to the path 'C:\Users\path\to\filename.xsl' is denied.'
            }
            catch (System.Exception e)
            {
                throw e;
            }
        }
    }
}

MainPage.xaml

<Page
    x:Class="XML2PDF.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XML2PDF"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid x:Name="BackgroundGrid" Background="Transparent" AllowDrop="True" DragEnter="BackgroundGrid_DragEnter" Drop="BackgroundGrid_Drop" />
</Page>

Package.appmanifest

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  IgnorableNamespaces="uap mp">

  ...

  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

Edit

It seems to be a permission problem. I updated ConvertXML2PDF method to read the file returne from drag-and-drop, and Package.appxmanifest to allow broad access. I put the file in Downloads. It throws an System.IO.FileNotFoundException. It is clear now that an app has no access to the file.

It's worthwhile to note that Visual Studio says <rescap:Capability Name="broadFileSystemAccess" /> has invalid child element namespace, which I'm not sure how to fix.

MainPage.xaml.cs

        private async void ConvertXML2PDF(string xmlPath, string xslPath)
        {
            Aspose.Pdf.Document pdf = new Aspose.Pdf.Document();
            string pdfPath = xmlPath.Replace(".xml", "pdf");

            Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
            Windows.Storage.StorageFile sampleFile = await storageFolder.GetFileAsync(xslPath);
            // System.IO.FileNotFoundException: The filename, directory name or volume label syntax is incorrect
        }

Package.appxmanifest

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap mp rescap">

  ...

  <Capabilities>
    <Capability Name="internetClient" />
    <rescap:Capability Name="broadFileSystemAccess" />
  </Capabilities>
</Package>
Watanabe.N
  • 1,549
  • 1
  • 14
  • 37
  • Where you setup file access ? I do not see it in appmanifest ... UWP apps have really narrow file access ... see "File access permissions" in offical UWP documentation – Selvin Jan 18 '23 at 11:49
  • thanks. I put files at Desktop or Download, either of them didn't work. I want a user to drag-and-drop their xml files (normally in Download, but it can be anywhere). From their documents, I thought as long as a user used filepicker or drag-and-drop, an app can access the files and folders. I'll read the document again. – Watanabe.N Jan 18 '23 at 12:12
  • Maybe drag-and-drop doesn't give an access like filepicker. – Watanabe.N Jan 18 '23 at 12:28
  • You drag both files ? – Selvin Jan 18 '23 at 12:29
  • Nevermind ... seems like UWP only allows to use file via `Windows.Storage` so if `Aspose` library is using `System.IO.*` then you are doomed – Selvin Jan 18 '23 at 12:37
  • @Selvin Yes, I did. – Watanabe.N Jan 18 '23 at 12:44
  • @Selvin Yes, I thought the same thing! – Watanabe.N Jan 18 '23 at 12:46
  • Check if `Aspose` can use Streams as input/output and then wrap `IOutputStream`/`IInputStream` into `System.IO.Stream` and pass it – Selvin Jan 18 '23 at 13:12
  • there is `BindXml(Stream, Stream)` ... open file using [`StorageFile.OpenAsync`](https://learn.microsoft.com/en-us/uwp/api/windows.storage.storagefile.openasync?view=winrt-22621) from UWP then use [`AsStream()`](https://learn.microsoft.com/en-us/dotnet/api/system.io?redirectedfrom=MSDN&view=net-7.0) – Selvin Jan 18 '23 at 13:15
  • The issue apparently looks related to access permissions. It should not be specific to the Aspose.PDF. Can you please try reading the files from same path using FileStreams and as suggested above, you can use the constructor of BindXml method that accepts stream. This is Asad Ali and I work as Developer Evangelist at Aspose. – Asad Ali Jan 18 '23 at 14:29
  • @Selvin Thanks. I updated the post. It seems a permission problem. I still can't fix it. – Watanabe.N Jan 18 '23 at 15:28
  • @AsadAli Thank you. I updated the post. It seems a permission problem. I still can't fix it. I'm happy to welcome you here. Sorry for cross-posting on Aspose forum. I'll update it later as well when solved. – Watanabe.N Jan 18 '23 at 15:28

1 Answers1

-1

UWP only allows to use file via Windows.Storage ... but you can convert it to "normal" Stream ... so as long as Aspose has some Stream API then you are home(and it seems it has)...

change your drop to:

private async void BackgroundGrid_Drop(object sender, DragEventArgs e)
{
    IStorageFile xmlFile = null;
    IStorageFile xslFile = null;

    if(e.DataView.Contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.StorageItems))
    {
        var items = (await e.DataView.GetStorageItemsAsync()).OfType<IStorageFile>();
        foreach(var item in items)
        {
            if(item.Path.EndsWith(".xml"))
            {
                xmlFile = item;
                continue;
            }
            if(item.Path.EndsWith(".xsl"))
            {
                xslFile = item;
                continue;
            }
        }
    }
    if(xmlFile != null && xslFile != null)
    {
        ConvertXML2PDF(xmlFile, xslFile);
    }
}

and ConvertXML2PDF method to:

    Aspose.Pdf.Document pdf = new Aspose.Pdf.Document();
    try
    {
        using(var xmlStream = await xmlFile.OpenStreamForReadAsync())
        {
            using(var xslStream = await xslFile.OpenStreamForReadAsync())
            {
                pdf.BindXml(xmlStream, xslStream);
         
                //C:\Users\User\AppData\Local\Packages\some_guid_6vqfjjxsnvvwr\LocalState
                //var pdfFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(xmlFile.Name.Replace("xml", "pdf"), CreationCollisionOption.ReplaceExisting);
                //or ask user
                var picker = new FileSavePicker();
                picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
                picker.FileTypeChoices.Add("PDF", new[] { ".pdf" });
                var pdfFile = await picker.PickSaveFileAsync();
                using(var pdfStream = await pdfFile.OpenStreamForWriteAsync())
                {
                    pdf.Save(pdfStream);
                }
            }
        }
    }
    catch(System.Exception e)
    {
        throw e;
    }

}

And you should be good to go

Selvin
  • 6,598
  • 3
  • 37
  • 43
  • Thanks. I'll give it a try. Is it possible to save a pdf where dragged XML is? In my Edit section of the post, I used `Windows.Storage`, but it couldn't access the file. Could you tell me what's wrong if you have a chance? – Watanabe.N Jan 18 '23 at 16:49
  • you searched for file `Windows.Storage.ApplicationData.Current.LocalFolder` which is something like `C:\Users\User\AppData\Local\Packages\some_guid_6vqfjjxsnvvwr\LocalState` + path to xml like `c:\Users\User\Desktop\whatever.xml` ... and file `C:\Users\User\AppData\Local\Packages\some_guid_6vqfjjxsnvvwr\LocalState\c:\Users\User\Desktop\whatever.xml` didn't existed – Selvin Jan 18 '23 at 16:52
  • Thanks. I was misunderstanding. I thought it reads as an absolute path instead of searching in current working directory. Sorry I edited the comment and asked about pdf saving location. Thanks for the very quick reply! – Watanabe.N Jan 18 '23 at 16:54
  • I understood your answer now that it saves where XML is. Thanks! – Watanabe.N Jan 18 '23 at 17:05
  • `pdf.BindXml` throws an `System.PlatformNotSupportedException: 'Compilation of XSLT is not supported on this platform.'` – Watanabe.N Jan 19 '23 at 03:57
  • Well, seems like you out of luck and BindXml doesn't work on UWP – Selvin Jan 19 '23 at 09:28
  • Exactly. I'm trying to convert into html and then pdf. Thank you a lot anyway. – Watanabe.N Jan 19 '23 at 09:57