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