Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to handle XML parsing errors? 1

Status
Not open for further replies.

PPettit

IS-IT--Management
Sep 13, 2003
511
US
I've got a script that loads numerous XML files from a directory, runs various data entry checks on each one, and then generates a report of all the errors. It runs fine except when it runs into invalid data (such as an ampersand).

For example, if my XML file contains something like this:
Code:
<Name>This & That</Name>
I get an error like this in the console:
Exception calling "Load" with "1" argument(s): "An error occurred while parsing EntityName. Line 40, position 37."
At :line:8 char:9
+ $xd.load <<<< ($file)

This leads me to two questions:
1. How do I force my script to continue processing the files instead of stopping at the problem file?
2. Is there a way to output the error message to my report file instead of the console?

In case it helps, this is a basic version of my script:
Code:
cls  #clear the console screen
[System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
$report = "X:\XML_CHECK.txt"  #set the file you want to use for the results
Clear-Content $report  #clears out everything so that you don't start off with old results

Foreach ($file in Get-Childitem X:\Test\*.xml)
	{
	$xd.load($file)
	$company = $xd.DocumentElement.SoldTo.Company.Name
	[string] $invoicenumber = $file.BaseName
	switch ($company)
		{
		"Company A"
			{Write-Output "$invoicenumber - $company" | Out-File $report -Append}
		"Company B"
			{Write-Output "$invoicenumber - $company" | Out-File $report -Append}
		default
			{Write-Output "$invoicenumber - $company is not an electronic invoicing customer." | Out-File $report -Append}
		}
	}
notepad $report
 
I think I figured out something that should work for me. The key was to use a "trap".

Revised code:
Code:
cls
[System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
$report = "X:\XML_CHECK.txt"  #set the file you want to use for the results
Clear-Content $report  #clears out everything so that you don't start off with old results

Foreach ($file in Get-Childitem X:\Test\*.xml)
	{
	[string] $invoicenumber = $file.BaseName
	$xd.load($file)
	[red]trap {Write-Output "$invoicenumber - [ERROR] $_)"  | Out-File $report -Append; Continue}[/red]  # "$_)" appears to be the variable containing the error message. 
	$company = $xd.DocumentElement.SoldTo.Company.Name
	switch ($company)
        {
        "Company A"
            {Write-Output "$invoicenumber - $company" | Out-File $report -Append}
        "Company B"
            {Write-Output "$invoicenumber - $company" | Out-File $report -Append}
        default
            {Write-Output "$invoicenumber - $company is not an electronic invoicing customer." | Out-File $report -Append}
        }
    }
notepad $report

Now, if I run across an ampersand, the error is written to the report and the script continues on. The error looks like this:
Code:
376467 - [ERROR] An error occurred while parsing EntityName. Line 40, position 37.)
 
I thought that it might be a good idea to pass this along as well.

I wanted to make my script do one thing if the file loaded properly, and another thing if didn't. I couldn't figure out how to determine if the trap had been triggered, but then I stumbled upon this:
$? Contains the execution status of the last operation. It contains TRUE if the last operation succeeded and FALSE if it failed.

I added something similar to this right after the trap statement:
Code:
If ($?)  # $? must be used immediately after the trap statement in order to determine whether or not the trap was triggered.  If you put another command before the line containing $?, $? will contain the execution status of that command instead of the trap command
  {
  #TRUE if no error, continue processing this file
  }
Else  
  {
  #FALSE if error is triggered, report the error but don't do anything else with this file
  }

There's probably a more elegant solution than this, but it works for me.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top