//---------------------------------------------------------------------
// File: XmlValidationStep.cs
//
// Summary:
// v1.1 - Updated by Daniel Probert.
// Uses .NET 2.0 XmlReader class to perform Xsd validation,
// and combines SelectSingleNode and XPathNavigator functionality
// into a single class.
//---------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//---------------------------------------------------------------------
namespace Microsoft.Services.BizTalkApplicationFramework.BizUnit
{
using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
///
/// The XmlValidationStep validates an Xml document, it may validate against a given schema, and also evaluate XPath queries.
///
///
///
/// The following shows an example of the Xml representation of this test step.
///
///
///
/// .\TestData\PurchaseOrder.xsd
/// urn:bookstore-schema
///
/// PONumber_0
///
///
///
///
///
///
/// Tag
/// Description
///
/// -
/// XmlSchemaPath
/// The XSD schema to use to validate the XML data (optional)
///
/// -
/// XmlSchemaNameSpace
/// The XSD schema namespace to validate the XML data against (optional)
///
/// -
/// XPathList/XPathValidation
/// XPath expression to evaluate against the XML document is defined in the attribute query, the expected result is defined in the element (optional)(repeating)
///
///
///
public class XmlValidationStep : IValidationStep
{
///
/// IValidationStep.ExecuteValidation() implementation
///
/// The stream cintaining the data to be validated.
/// The Xml fragment containing the configuration for the test step
/// The context for the test, this holds state that is passed beteen tests
public void ExecuteValidation(Stream data, XmlNode validatorConfig, Context context)
{
string xmlSchemaPath = context.ReadConfigAsString(validatorConfig, "XmlSchemaPath", true);
string ns = context.ReadConfigAsString(validatorConfig, "XmlSchemaNameSpace", true);
XmlNodeList xpaths = validatorConfig.SelectNodes("XPathList/*");
XmlDocument doc = new XmlDocument();
XmlTextReader trData = new XmlTextReader(data);
// If schema was specified use it to validate against...
if (null != xmlSchemaPath)
{
FileInfo fi = new FileInfo(xmlSchemaPath);
// Store the current diretcory whilst we temporarily change it
string currentDirectory = Environment.CurrentDirectory;
// Change the current directory to the schema location so that
// any relative imports/includes in the schema will work correctly
Environment.CurrentDirectory = fi.DirectoryName;
MemoryStream xsdSchema = StreamHelper.LoadFileToStream(xmlSchemaPath);
XmlTextReader trSchema = new XmlTextReader(xsdSchema);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
if (null != ns)
{
settings.Schemas.Add(ns, trSchema);
}
else
{
settings.Schemas.Add(null, trSchema);
}
XmlReader vr = XmlReader.Create(trData, settings);
while (vr.Read()) { }
// Reset the current directory
Environment.CurrentDirectory = currentDirectory;
}
data.Seek(0, SeekOrigin.Begin);
doc.Load(data);
foreach (XmlNode xpath in xpaths)
{
string xpathExp = xpath.SelectSingleNode("@query").Value;
XmlNode valNode = xpath.SelectSingleNode(".");
string nodeValue = valNode.InnerText;
context.LogInfo("XmlValidationStep evaluating XPath {0} equals \"{1}\"", xpathExp, nodeValue);
XmlNode checkNode = null;
try
{
checkNode = doc.SelectSingleNode(xpathExp);
}
catch { }
if (checkNode != null)
{
if (0 != nodeValue.CompareTo(checkNode.InnerText))
{
throw new ApplicationException(string.Format("XmlValidationStep failed, compare {0} != {1}, xpath query used: {2}", nodeValue, checkNode.InnerText, xpathExp));
}
}
else
{
XPathNavigator xpn = doc.CreateNavigator();
object result = xpn.Evaluate(xpathExp);
string checkValue = null;
if (result.GetType().Name == "XPathSelectionIterator")
{
XPathNodeIterator xpi = result as XPathNodeIterator;
xpi.MoveNext();
if (null != xpi)
{
checkValue = xpi.Current.ToString();
}
}
else
{
checkValue = result.ToString();
}
if (0 != nodeValue.CompareTo(checkValue))
{
throw new ApplicationException(string.Format("XmlValidationStep failed, compare {0} != {1}, xpath query used: {2}", nodeValue, checkValue, xpathExp));
}
}
}
}
}
}