2

I'm trying to clean XML Files with an XSL Transformation. When I'm applying my XSL directly to my XML File, it works fine. But now I want to clean every XML File I have in a directory. I've tried to create a PowerShell script, to load and transform XML Files.

Here is my code :

$dir = "C:\MyDirectory"
$XSLFileName = "XSLTFile.xsl"
$XSLFileInput = $dir + $XSLFileName

$XMLFileName = "Input.xml"
$XMLInputFile = $dir + $XMLFileName
$OutputFileName = "Output.xml"
$XMLOutputFile = $dir + $OutputFileName

cd $dir 

$XSLInputElement = New-Object System.Xml.Xsl.XslCompiledTransform;
$XSLInputElement.Load($XSLFileInput)

$XMLInputDoc = Get-Content -Path $XMLInputFile

$reader = [System.Xml.XmlReader]::Create($XMLInputFile)
$writer = [System.Xml.XmlTextWriter]::Create($XMLOutputFile)

$XSLInputElement.Transform($XMLInputDoc, $writer)

I've been threw some docs and SO subjects to find how to use the Transform() method, but I haven't found how to deal with this error :

Exception calling "Transform" with "2" argument(s): "Caractères non conformes dans le chemin d'accès."
At C:\ScirptsDirs\StackOverFlowTransformExample.ps1:20 char:1
+ $XSLInputElement.Transform($XMLInputDoc, $writter)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException

Note : "Caractères non conformes dans le chemin d'accès." means : Invalid symbol found in the access path.

What I want to do is to clean my XML File, and to create an other XML File but with the XSL Transformation applied to it.

EDIT : I've also tried this way, as Martin said :

$XSLInputElement.Transform($XMLInputFile, $XMLOutputFile)

But this time, I have thee following error :

Exception calling "Transform" with "2" argument(s): "Execution of the 'document()' function was prohibited. Use the XsltSettings.EnableDocumentFunction property to enable it. An error occurred at  D:\MyDirectory\XSLTFile.xsl(220,3)."
At C:\ScirptsDirs\StackOverFlowTransformExample.ps1:20 char:1
+ $XSLInputElement.Transform($XMLInputFile, $XMLOutputFile)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : XslTransformException
dStulle
  • 609
  • 5
  • 24
Vincent G
  • 361
  • 1
  • 4
  • 22

2 Answers2

3

If you have the input and output file name respectively path as a string then simply use $XSLInputElement.Transform($XMLInputFile, $XMLOutputFile).

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thanks Martin, but it's not working, i've tried this way, and I have an other error. I've edited my question so that you will be able to see the other error raised when I try your with your method. – Vincent G May 04 '16 at 11:33
  • 1
    Well, that error suggests that the `Transform` call with the arguments as suggested is working, only that the XSLT stylesheet you use calls the `document` function, so that you first need to make sure you use `$XsltSettings = New-Object System.Xml.Xsl.XsltSettings(true, false);` and `$XSLInputElement = New-Object System.Xml.Xsl.XslCompiledTransform; $XSLInputElement.Load($XSLFileInput, $XsltSettings, New-Object System.Xml.XmlUrlResolver);` – Martin Honnen May 04 '16 at 11:48
  • 1
    The right Powershell syntax to create boolean parameters seems to be `$XsltSettings = New-Object System.Xml.Xsl.XsltSettings($true, $false);` – Martin Honnen May 04 '16 at 11:57
  • I've done it this way : `$XsltSettings = New-Object System.Xml.Xsl.XsltSettings $XsltSettings.EnableDocumentFunction = 1` – Vincent G May 04 '16 at 11:58
3

This is working for me. The extra lines are for enabling scripts in the xsl.

EDIT. Seems the solution to above was that a line to enable the document function was needed. Similar to how I enable scripts.

$xslt_settings.EnableDocumentFunction = 1;

could be added to my function

function TransformXML{
    param ($xml, $xsl, $output)

    if (-not $xml -or -not $xsl -or -not $output)
    {
        Write-Host "& .\xslt.ps1 [-xml] xml-input [-xsl] xsl-input [-output] transform-output"
        return 0;
    }

    Try
    {
        $xslt_settings = New-Object System.Xml.Xsl.XsltSettings;
        $XmlUrlResolver = New-Object System.Xml.XmlUrlResolver;
        $xslt_settings.EnableScript = 1;

        $xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
        $xslt.Load($xsl,$xslt_settings,$XmlUrlResolver);
        $xslt.Transform($xml, $output);

    }

    Catch
    {
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        Write-Host  'Error'$ErrorMessage':'$FailedItem':' $_.Exception;
        return 0
    }
    return 1

}
vikjon0
  • 182
  • 1
  • 12
  • This solution worked great for me. One small correction is the initial return 0 statement has a typoe. – foxfire Jun 22 '17 at 18:57
  • Thanks, fixed the typo (finally) – vikjon0 Jan 17 '18 at 08:21
  • 1
    after re-reading and this time understanding the comments to the accepted answer the original poster needed $xslt_settings.EnableDocumentFunction = 1; While my problem was that I was using a vbs script in the xsl and needed $xslt_settings.EnableScript = 1; Generally the problem in both cases was lack of understanding of the XsltSettings object. – vikjon0 Jan 17 '18 at 08:30