using System; using System.IO; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; using System.Xml; using System.Xml.Schema; using System.Xml.Xsl; using System.Xml.XPath; using System.Data.OleDb; using System.Text.RegularExpressions; namespace com.cloudsoft.utils { /// /// Class contains methods for constructing and querying XML doms /// /// public class XMLHelper { // Declare module level variables /// The Node that this XMLHelper wraps protected XmlNode omNode; protected Boolean isValidXml = true; public String ValidationError; private static String _QUOTE = "\""; private Regex _DatePattern = null; private Regex _DoublePattern = null; internal OleDbConnection _con = null; #region Constructors /// Creates a new instance of XMLHelper public XMLHelper() { } /// /// Creates a new instance of XMLHelper with the base node set /// /// The root node to create or an XML Document to load public XMLHelper(String zRoot) { if (zRoot.Contains("<") || zRoot.Contains("<") || zRoot.Contains("\\")) //WADS: Cross site scripting... load(zRoot); else //WADS: XPath Injection... createRoot(zRoot); } public XMLHelper(StringBuilder zRoot) { load(zRoot); } public XMLHelper(Stream stream) { load(stream); } /// /// Creates a new instance of XMLHelper with the base node set /// /// The base node to set public XMLHelper(XmlNode oNode) { omNode = oNode; } /// /// Creates a new instance of XMLHelper with the base node set to the first child of the Document /// /// Document to base this XMLHelper on public XMLHelper(XmlDocument oDoc) { omNode = (XmlNode)oDoc.DocumentElement; } #endregion #region IO & Save Methods /// /// Saves the dom to the specified path. Always overwrites anything already there. /// /// The path to save to. public void SaveAs(String path) { try { //Overwrite any existing files... FileInfo fi = new FileInfo(path); if (fi.Exists) fi.Delete(); } catch { //If you can't delete the file then don't try and overwrite it... return; } StreamWriter sw = new StreamWriter(path); try { //Set up a stream... sw.AutoFlush = true; //Write to the stream and close it... sw.WriteLine(""); sw.Write(this.getXML()); } finally { sw.Close(); sw.Dispose(); } } #endregion #region "Helper" methods /// /// Creates a Standard Request DOM /// /// The type of request /// The mud id /// The system id /// public XMLHelper createStandardRequest(String zType, String zMudID, String zSystem) { return createStandardRequest(zType, zMudID, zSystem, zMudID); } /// /// Handles delegation /// /// /// /// /// /// public XMLHelper createStandardRequest(String zType, String zMudID, String zSystem, String UserLogon) { this.createRoot("request"); this.appendAttribute("type", zType); this.appendNode("mud_id", zMudID); this.appendNode("system", zSystem); string zDeligateUser = UserLogon; string[] aSplit = zDeligateUser.Split("\\".ToCharArray()); zDeligateUser = aSplit[aSplit.Length - 1].ToUpper(); if (zMudID != zDeligateUser) this.appendNode("delegate_id", zDeligateUser); return this; } #endregion #region Dom Manipulation /// /// Creates the root Node /// /// The name of the root node public void createRoot(String zRootName) { //WADS: XPath Injection... this.load("<" + zRootName + "/>"); } /// /// Appends a node to the dom /// /// The name of the new node /// Returns an XMLHelper of the new Node public XMLHelper appendNode(String vNodeName) { XmlDocument oDoc = omNode.OwnerDocument; XmlNode oNewNode = oDoc.CreateElement(vNodeName); omNode.AppendChild(oNewNode); XMLHelper oHelper = new XMLHelper(oNewNode); return oHelper; } /// /// Appends a node to the dom and sets it's value /// /// The name of the new node /// The value to set the new node /// Returns the XMLHelper for the new node public XMLHelper appendNode(String vNodeName, Object zValue) { XmlDocument oDoc = omNode.OwnerDocument; XmlNode oNewNode = oDoc.CreateElement(vNodeName); oNewNode.AppendChild(oDoc.CreateTextNode(zValue == null ? "" : zValue.ToString())); omNode.AppendChild(oNewNode); XMLHelper oHelper = new XMLHelper(oNewNode); return oHelper; } /// /// Appends an XMLHelper dom /// /// The DOM to append to this DOM /// Returns the XMLHelper for the new node public XMLHelper appendNode(XMLHelper oDOM) { XmlNode oNew = omNode.OwnerDocument.ImportNode(oDOM.omNode, true); omNode.AppendChild(oNew); return new XMLHelper(oNew); } /// /// Appends a NameValueCollection to the DOM as Nodes /// /// The DOM to append to this DOM public void appendNode(NameValueCollection oCol) { // Iterate through the collection and add // each name value pair to the dom for (int i = 0; i < oCol.Count; i++) { String zName = oCol.GetKey(i); String[] pValues = oCol.GetValues(i); for (int j = 0; j < pValues.Length; j++) appendNode(zName, pValues[j]); } } /// /// Appends an array of XMLHelpers /// /// The Nodelist to append to the existing DOM public void appendNode(XMLHelper[] oNodes) { for (int i = 0; i < oNodes.Length; i++) appendNode(oNodes[i]); } /// /// Appends an attribute to the dom and sets it's value /// /// The name of the new node /// The value to set the new node public void appendAttribute(String zNodeName, String zValue) { // Attr oAttr = omNode.getOwnerDocument().createAttribute(zNodeName); // oAttr.setNodeValue(zValue); // omNode.appendChild(oAttr); XmlElement oNode = (XmlElement)omNode; oNode.SetAttribute(zNodeName, zValue); } /// /// Retrieved the root node of a XMLHelper dom /// /// Returns the Root Node for this XMLHelper DOM public XMLHelper getRootNode() { return new XMLHelper(omNode.OwnerDocument); } public void appendXPathNode(String zXPath, String zValue) { appendXPathNode(zXPath, zValue, true); } /// /// Appends a node/attribute based on an XPath (like alias names in SQL) /// /// The name of the new node/attribute in XPath syntax /// The value to set the new node public void appendXPathNode(String zXPath, String zValue, Boolean AlwaysAddNewNode) { try { int i; XmlNode oOrig = omNode; // Split the Name by "/" String[] arrNodes = zXPath.Split(new char[] { '/' }); for (i = 0; i < arrNodes.Length - 1; i++) { XmlNode oNode = omNode.SelectSingleNode(arrNodes[i]); if (oNode == null) omNode = appendNode(arrNodes[i]).omNode; else omNode = oNode; } if (arrNodes[i].StartsWith("@")) appendAttribute(arrNodes[i].Substring(1), zValue); else { if (AlwaysAddNewNode) { appendNode(arrNodes[i], zValue); } else { if (this.nodeCount(arrNodes[i]) > 0) { this.getNode(arrNodes[i]).setValue(zValue); } else { appendNode(arrNodes[i], zValue); } } } omNode = oOrig; } catch (Exception ex) { System.Console.WriteLine(ex.Message); } } /// /// Removes a node given the nodename /// /// The name of node to remove public void removeNode(String zNodeName) { try { XmlNode oTempNode = omNode.SelectSingleNode(zNodeName); if (oTempNode != null) oTempNode.ParentNode.RemoveChild(oTempNode); } catch { // Do nothing if we can't remove the node } } #endregion #region Serialisation /// /// Searalises the current tree from the current Node to a Writer (like Resonse.Output) /// /// The Writer to write the XML to (eg. Resonse.Output) public void serializeNode(TextWriter oWriter) { try { serializeNode(omNode, oWriter); } catch (Exception ex) { System.Console.WriteLine(ex.Message); } } /// /// Serializes the node. /// /// The node. /// The writer. private void serializeNode(XmlNode oNode, TextWriter oWriter) { try { oWriter.Write(oNode.OuterXml); } catch (Exception ex) { System.Console.WriteLine(ex.Message); } } /// /// Serializes the node. /// /// The node. /// An XML String private String serializeNode(XmlNode oNode) { try { return (oNode.OuterXml); } catch (Exception ex) { System.Console.WriteLine(ex.Message); return (""); } } public String getJSON() { StringWriter stringOut = new StringWriter(); getJSON(stringOut); return (stringOut.ToString()); } public void getJSON(TextWriter oOut) { oOut.Write("{"); getJSON(omNode.OwnerDocument.FirstChild, false, oOut); oOut.Write("}"); } private void getJSON(XmlNode oNode, Boolean isArray, TextWriter oOut) { String zName = oNode.Name; if (zName.Equals("#text")) zName = "$"; if (!isArray) oOut.Write(_QUOTE + zName + _QUOTE + ":"); if (isJSONArray(oNode.ChildNodes)) { oOut.Write("["); getJSON(oNode.ChildNodes, true, oOut); oOut.Write("]"); } else if (oNode.NodeType == XmlNodeType.Attribute) { oOut.Write(getJSONValue(oNode.Value)); } else if (!oNode.HasChildNodes && (oNode.Attributes == null || oNode.Attributes.Count == 0)) { if (oNode.Value == null) oOut.Write("null"); else oOut.Write(getJSONValue(oNode.Value)); } else if (oNode.Attributes.Count == 0 && oNode.ChildNodes.Count == 1 && !oNode.FirstChild.HasChildNodes) { oOut.Write(getJSONValue(oNode.FirstChild.Value)); } else { oOut.Write("{"); getJSON(oNode.Attributes, oOut); if (oNode.Attributes.Count > 0 && oNode.ChildNodes.Count > 0) oOut.Write(","); getJSON(oNode.ChildNodes, false, oOut); oOut.Write("}"); } } private void getJSON(XmlNodeList oNodeList, Boolean isArray, TextWriter oOut) { for (int i = 0; i < oNodeList.Count; i++) { XmlNode oNode = oNodeList.Item(i); if (i > 0) oOut.Write(","); getJSON(oNode, isArray, oOut); } } private void getJSON(XmlAttributeCollection oNodeMap, TextWriter oOut) { for (int i = 0; i < oNodeMap.Count; i++) { XmlNode oNode = oNodeMap.Item(i); if (i > 0) oOut.Write(","); getJSON(oNode, false, oOut); } } private String getJSONValue(String zValue) { zValue = zValue.Trim(); if (DatePattern().IsMatch(zValue)) { DateTime matchDate = DateTime.Now; try { matchDate = DateTime.Parse(zValue); } catch (Exception ex) { } String ret = "new Date(" + matchDate.Year + "," + (matchDate.Month - 1) + "," + matchDate.Day; if (zValue.Length > 11) ret += "," + matchDate.Hour + "," + matchDate.Minute + "," + matchDate.Second; ret += ")"; return ret; } else if (zValue.Length <= 10) { try { return int.Parse(zValue).ToString(); } catch (Exception ex) { } if (DoublePattern().IsMatch(zValue)) return zValue; //try { return Double.Parse(zValue).ToString();} //catch (Exception ex) {} } return _QUOTE + zValue.Replace("\\", "\\\\").Replace("\"", "\\\"") + _QUOTE; } private Boolean isJSONArray(XmlNodeList oNodeList) { if (oNodeList.Count < 1 || (oNodeList.Count == 1 && (oNodeList.Item(0).Name + "s") != oNodeList.Item(0).ParentNode.Name)) return (false); String zName = oNodeList.Item(0).Name; for (int i = 0; i < oNodeList.Count; i++) { if (!oNodeList.Item(i).Name.Equals(zName)) return (false); } return (true); } private Regex DatePattern() { if (_DatePattern == null) { _DatePattern = new Regex("^(([0-9])|([0-2][0-9])|([3][0-1]))-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\\d{4}.*", RegexOptions.IgnoreCase); } return _DatePattern; } private Regex DoublePattern() { if (_DoublePattern == null) { _DoublePattern = new Regex("^[-+]?[0-9]*\\.?[0-9]+$"); } return _DoublePattern; } #endregion #region Load Methods /// /// Loads a string into the DOM or a file. Either an XML string or a file location may be used /// /// Either the XML as a string or a file location /// Boolean indicating success or failure public Boolean load(String zXML) { try { XmlDocument oDOM = new XmlDocument(); if (zXML.StartsWith("<") || zXML.StartsWith("<")) //WADS: XPath Injection... oDOM.LoadXml(zXML); else //WADS: XPath Injection... oDOM.Load(zXML); omNode = (XmlNode)oDOM.DocumentElement; return true; } catch (Exception ex) { throw new Exception("Can't load dom. Error: " + ex.Message); } } public Boolean load(Stream stream) { try { XmlDocument oDOM = new XmlDocument(); oDOM.Load(stream); omNode = (XmlNode)oDOM.DocumentElement; return true; } catch (Exception ex) { throw new Exception("Can't load dom. Error: " + ex.Message); } } public Boolean load(StringBuilder zXML) { try { StringReader sr = new StringReader(zXML.ToString()); XmlReader xr = XmlReader.Create(sr); XmlDocument oDOM = new XmlDocument(); oDOM.Load(xr); omNode = (XmlNode)oDOM.DocumentElement; return true; } catch (Exception ex) { throw new Exception("Can't load dom. Error: " + ex.Message); } } public Boolean loadTSV(String zPath) { try { // Create an instance of StreamReader to read from a file. // The using statement also closes the StreamReader. this.createRoot("response"); XMLHelper oRows = this.appendNode("rows"); using (StreamReader sr = new StreamReader(zPath)) { String[] aHeader = null; String line; // Read and display lines from the file until the end of // the file is reached. while ((line = sr.ReadLine()) != null) { // Get the header if we don't have it if (aHeader == null) { aHeader = line.Split('\t'); } else { String[] aFields = line.Split('\t'); int i = 0; XMLHelper oRow = oRows.appendNode("row"); foreach (String zHeader in aHeader) oRow.appendNode(zHeader, aFields[i++]); } } } return true; } catch (Exception e) { // Let the user know what went wrong. throw new Exception("The file could not be read: " + e.Message); } } #endregion #region Get and Set Methods /// /// Retrieved the child nodes an XMLHelper dom /// /// Returns the Child nodes as an array public XMLHelper[] getChildNodes() { XmlNodeList oNodes = omNode.ChildNodes; XMLHelper[] arrNodes = new XMLHelper[oNodes.Count]; for (int i = 0; i < oNodes.Count; i++) arrNodes[i] = new XMLHelper(oNodes.Item(i)); return arrNodes; } public XMLHelper getFirstChild() { return new XMLHelper(omNode.FirstChild); } public DateTime getSQLDate(String zXPath) { return getDate(zXPath); } public DateTime getSQLDateTime(String zXPath) { return getDate(zXPath); } /// /// Gets the XML of the current node as a string /// /// Returns the XML of the current node as a string public String getXML() { return serializeNode(omNode); } /// /// Gets the InnerXML of the current node as a string /// /// Returns the InnerXML of the current node as a string public String getInnerXML() { return omNode.InnerXml; } /// /// Gets the XML of the root node as a string /// /// Returns the XML of the root node as a string public String getRootXML() { return omNode.OwnerDocument.OuterXml; } /// /// Get the parent XMLHelper /// /// Returns the Parent node as an XMLHelper object public XMLHelper getParent() { XMLHelper oHelper = new XMLHelper(omNode.ParentNode); return oHelper; } /// /// Returns the Name of a node or element /// /// The node name of the current node public String getName() { try { return omNode.Name; } catch (Exception) { return ""; } } /// /// Returns the value of a node or element /// JF 12/2007 - Added a check for a null valued XMLHelper (with a null omNode) /// rather than relying on the exception handler. /// /// The nodevalue of the current node public String getValue() { if (omNode != null) { try { return omNode.InnerText; } catch (Exception) { return ""; } } else { return ""; } } /// /// Returns the value of a node or element as a string /// /// A valid XPath to find a node /// The nodevalue of the Node found as a string public String getValue(String zXPath) { return getNode(zXPath).getValue(); } /// /// Returns the value of a node or element as a string /// /// A valid XPath to find a node /// The nodevalue of the Node found as a string public String getString(String zXPath) { return getValue(zXPath); } /// /// Returns the value of a node or element as a long /// /// A valid XPath to find a node /// The nodevalue of the Node found as a long public long getLong(String zXPath) { try { return Convert.ToInt64(getValue(zXPath).Trim()); } catch (Exception) { return 0; } } /// /// Returns the value of a node or element as an int /// /// A valid XPath to find a node /// The nodevalue of the Node found as an int public int getInt(String zXPath) { try { String value = getValue(zXPath).Trim(); if (value.Length > 0) { return Convert.ToInt32(value); } else { return 0; } } catch (Exception) { return 0; } } /// /// Returns the value of a node or element as a double /// /// A valid XPath to find a node /// The nodevalue of the Node found as a double public double getDouble(String zXPath) { try { return Convert.ToDouble(getValue(zXPath).Trim()); } catch { return 0.0; } } /// /// Returns the value of a node or element as a DateTime Object /// /// A valid XPath to find a node /// The nodevalue of the Node found as a DateTime Object public DateTime getDate(String zXPath) { DateTime d = DateTime.MinValue; try { DateTime.TryParse(getValue(zXPath).Trim(), out d); } catch { } return d; } /// /// Returns the value of a node or element as a Boolean /// /// A valid XPath to find a node /// The nodevalue of the Node found as a Boolean public Boolean getBoolean(String zXPath) { String zVal = getValue(zXPath).ToUpper(); return (zVal.Equals("Y") || zVal.Equals("YES") || zVal.Equals("TRUE")); } /// /// Returns the value of a node or element as either Y or N /// /// A valid XPath to find a node /// The nodevalue of the Node found as a Boolean public String getYN(String zXPath) { return (getBoolean(zXPath) ? "Y" : "N"); } /// /// Returns an XMLHelper for a XPath /// /// A valid XPath to find a node /// XMLHelper for a XPath public XMLHelper getNode(String zXPath) { XmlNode oNode; try { oNode = omNode.SelectSingleNode(zXPath); return new XMLHelper(oNode); } catch { // JF 12/2007 - Don't just blindly return an empty XMLHelper if the getNode fails. // Should create an alternative function for this purpose if it is ever required. throw new Exception("Can't get node for xpath: " + zXPath); } } /// /// Returns an Array of XMLHelper objects for a XPath /// /// A valid XPath to find a node /// Array of XMLHelper object for a XPath public XMLHelper[] getNodes(String zXPath) { try { XmlNodeList oNodes = omNode.SelectNodes(zXPath); XMLHelper[] arrNodes = new XMLHelper[oNodes.Count]; for (int i = 0; i < oNodes.Count; i++) arrNodes[i] = new XMLHelper(oNodes.Item(i)); return arrNodes; } catch (Exception ex) { System.Console.WriteLine(ex.Message); return null; } } /// /// Gets a CSV string given an XPath /// /// The XPath. /// A CSV String public String getCSV(String zXPath) { StringWriter oSW = new StringWriter(); XmlNodeList oNodes = omNode.SelectNodes(zXPath); for (int i = 0; i < oNodes.Count; i++) { if (i > 0) oSW.Write(','); oSW.Write(oNodes[i].InnerText); } return oSW.ToString(); } /// /// Sets a Nodes value /// /// The name of the node to set /// The value to set the node public void setNode(String zNodeName, String zValue) { removeNode(zNodeName); appendNode(zNodeName, zValue); } /// /// Sets a Nodes value /// /// The name of the node to set /// The value to set the node public void setValue(String zValue) { omNode.InnerText = zValue; } /// /// Sets an attribute value /// /// The name of the attribute to set /// The value to set the attribute public void setAttribute(String zAttributeName, String zValue) { omNode.Attributes[zAttributeName].Value = zValue; } public void setAttribute(String zAttributeName, Int32 iValue) { omNode.Attributes[zAttributeName].Value = iValue.ToString(); } /// /// Gets the numbers of rows given an XPath /// /// The Xpath to get the nodecount for /// The number of nodes for the given Xpath public int nodeCount(String zXPath) { try { XmlNodeList oNodes = omNode.SelectNodes(zXPath); return (oNodes.Count); } catch { return 0; } } public XPathNodeIterator getIterator(String sourceNodePath) { XPathNavigator nav = omNode.CreateNavigator(); XPathExpression expression = nav.Compile(sourceNodePath); return nav.Select(expression); } #endregion #region Testing /// /// Test Harness /// /// the command line arguments public static void Main(String[] args) { // Test simple Load XMLHelper oDOM = new XMLHelper(); // Test creating a DOM by handing and manipulating it oDOM.createStandardRequest("test_type", "PYL38997", "CIMS"); oDOM.appendNode("test", "value"); System.Console.WriteLine("test:" + oDOM.getValue("test")); System.Console.WriteLine("@type:" + oDOM.getValue("@type")); oDOM.removeNode("test"); System.Console.WriteLine(oDOM.getRootXML()); // More manipulation oDOM.appendNode("test", "value"); oDOM.setNode("test", "new Value"); oDOM = oDOM.appendNode("groups"); for (int i = 0; i < 10; i++) oDOM.appendNode("group").appendAttribute("id", Convert.ToString(i)); // Test getNodes XMLHelper[] oNodes = oDOM.getNodes("//group"); for (int i = 0; i < oNodes.Length; i++) System.Console.WriteLine(oNodes[i].getXML()); System.Console.WriteLine(oDOM.getRootXML()); // Test appending an entirely new DOM XMLHelper oNew = new XMLHelper("new"); oNew.appendNode("test", "40213423"); oDOM.appendNode(oNew); System.Console.WriteLine(oDOM.getRootXML()); // Test appending a Nodelist oNew.appendNode(oNodes); System.Console.WriteLine(oNew.getRootXML()); System.Console.WriteLine(oDOM.getRootNode().getChildNodes().Length); System.Console.WriteLine(oDOM.omNode.OwnerDocument.GetElementsByTagName("group").Count); System.Console.WriteLine(oDOM.getParent().getNode("group").getXML()); XMLHelper o = new XMLHelper("response"); o.appendXPathNode("customer/@id", "1"); o.appendXPathNode("customer/name/first", "john"); o.appendXPathNode("customer/name/last", "doe"); o.appendNode("date", "01-jan-2005"); o.appendNode("empty_date", ""); System.Console.WriteLine(o.getDate("date")); System.Console.WriteLine(o.getDate("empty_date")); System.Console.WriteLine(o.getRootXML()); System.Console.WriteLine(o.omNode.ChildNodes.Count); System.Console.WriteLine("Inner : " + o.getInnerXML()); } #endregion #region Distinct XML /// /// Appends a distinct set of the specified nodes to the current document. /// See description for other appendDistinct overload (Example 1). /// public void appendDistinct(String sourceNodePath, String keyAttribute, String resultRoot) { appendDistinct(sourceNodePath, keyAttribute, resultRoot, null, ""); } /// /// High performance option for append distinct. /// Allows direct access with an iterator. /// Useful if adding multiple distincts from the same source rowset. /// /// /// /// /// /// /// Forces the iterator to select nodes rather than attributes public void appendDistinct(XPathNodeIterator incomingIterator, String keyAttribute, String resultRoot, String[] additionalAttributes, String resultNodesName, Boolean UseNodes) { string value; string attribute; SortedList ids = new SortedList(); MemoryStream ms = new MemoryStream(); XmlTextWriter xmlWriter = new XmlTextWriter(ms, Encoding.UTF8); xmlWriter.WriteStartElement(resultRoot); XPathNodeIterator iterator = incomingIterator.Clone(); while (iterator.MoveNext()) { if (UseNodes) attribute = keyAttribute; else attribute = "@" + keyAttribute; value = iterator.Current.SelectSingleNode(attribute).Value; if (!ids.ContainsKey(value)) { if (additionalAttributes != null) { xmlWriter.WriteStartElement(resultNodesName); xmlWriter.WriteAttributeString(keyAttribute, value); ids.Add(value, null); foreach (String extraNode in additionalAttributes) { if (UseNodes) attribute = extraNode; else attribute = "@" + extraNode; xmlWriter.WriteAttributeString(extraNode, iterator.Current.SelectSingleNode(attribute).Value); } xmlWriter.WriteEndElement(); } else { xmlWriter.WriteElementString(keyAttribute, value); ids.Add(value, null); } } } xmlWriter.WriteEndElement(); xmlWriter.Flush(); ms.Seek(0, System.IO.SeekOrigin.Begin); XmlDocument distinct = new XmlDocument(); distinct.Load(ms); xmlWriter.Close(); omNode.AppendChild(omNode.OwnerDocument.ImportNode(distinct.DocumentElement, true)); } public void appendDistinct(XPathNodeIterator incomingIterator, String keyAttribute, String resultRoot, String[] additionalAttributes, String resultNodesName) { appendDistinct(incomingIterator, keyAttribute, resultRoot, additionalAttributes, resultNodesName, false); } /// /// Appends a distinct set of the specified nodes to the current document. /// If additionalAttributes is null then resultNodesName is not used and the results will look /// like the first example. With additionalAttributes /// /// XPath to the nodes to be distincted. /// Attribute to key on for determining uniqueness. /// Name of the root node to create and append the distinct nodes to. /// Additional attributes to include in the distinct items. /// Name of individual result nodes. /// Use nodes instead of attributes for the data. /// /// /// /// Source: /// /// /// /// /// /// /// Example 1: appendDistinct("activities/activity", "customer_id", "customer_ids") /// /// 1 /// 2 /// /// /// Example 2: appendDistinct("activities/activity", "customer_id", "customers", new string[] { "name" }, "customer" ) /// /// /// /// /// /// public void appendDistinct(String sourceNodePath, String keyAttribute, String resultRoot, String[] additionalAttributes, String resultNodesName, Boolean UseNodes) { DateTime startTime = DateTime.Now; XPathNavigator nav = omNode.CreateNavigator(); XPathExpression expression = nav.Compile(sourceNodePath); XPathNodeIterator iterator = nav.Select(expression); appendDistinct(iterator, keyAttribute, resultRoot, additionalAttributes, resultNodesName, UseNodes); TimeSpan ExecutionDuration = DateTime.Now - startTime; this.getNode(resultRoot).appendAttribute("execution_duration", ExecutionDuration.TotalMilliseconds.ToString()); } public void appendDistinct(String sourceNodePath, String keyAttribute, String resultRoot, String[] additionalAttributes, String resultNodesName) { appendDistinct(sourceNodePath, keyAttribute, resultRoot, additionalAttributes, resultNodesName, false); } #endregion #region Validation public string validateXML(String schema) { StringReader srXml = new StringReader(getRootXML()); XmlValidatingReader vr; XmlTextReader tr; XmlSchemaCollection schemaCol = new XmlSchemaCollection(); XMLHelper oResponse = new XMLHelper("response"); try { schemaCol.Add(null, schema); isValidXml = true; // Read the xml. tr = new XmlTextReader(srXml); // Create the validator. vr = new XmlValidatingReader(tr); // Set the validation tyep. vr.ValidationType = ValidationType.Auto; // Add the schema. if (schemaCol != null) { vr.Schemas.Add(schemaCol); } // Set the validation event handler. vr.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); // Read the xml schema. while (isValidXml && vr.Read()) { } vr.Close(); oResponse.appendNode("valid", "true"); return oResponse.getRootXML(); } catch (Exception ex) { oResponse.appendNode("valid", "false"); oResponse.appendNode("error", ex.Message); ValidationError = ex.Message; return oResponse.getRootXML(); } finally { // Clean up... vr = null; tr = null; schemaCol = null; } } public Boolean validateUsing(String schema) { StringReader srXml = new StringReader(getRootXML()); XmlValidatingReader vr; XmlTextReader tr; XmlSchemaCollection schemaCol = new XmlSchemaCollection(); schemaCol.Add(null, schema); isValidXml = true; try { // Read the xml. tr = new XmlTextReader(srXml); // Create the validator. vr = new XmlValidatingReader(tr); // Set the validation tyep. vr.ValidationType = ValidationType.Auto; // Add the schema. if (schemaCol != null) { vr.Schemas.Add(schemaCol); } // Set the validation event handler. vr.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); // Read the xml schema. while (isValidXml && vr.Read()) { } vr.Close(); return isValidXml; } catch (Exception ex) { ValidationError = ex.Message; return false; } finally { // Clean up... vr = null; tr = null; } } private void ValidationCallBack(object sender, ValidationEventArgs args) { // The xml does not match the schema. isValidXml = false; ValidationError = args.Message; } #endregion #region XSL Transformation /// /// Transforms the current DOM using the XSL and returns an XMLHelper DOM /// /// The XSL for the transform /// XMLHelper DOM with the result of the transform public XMLHelper transform(String zXSL) { return transform(zXSL, new Dictionary()); } /// /// Transforms the current DOM using the XSL to a TextWriter /// /// The XSL for the transform /// Thre Textwriter to output to public void transform(String zXSL, TextWriter oOut) { transform(zXSL, new Dictionary(), oOut); } public XMLHelper transform(Stream oXSL) { return transform(oXSL, new Dictionary()); } public XMLHelper transform(Stream oXSL, Dictionary aParams) { StringWriter oText = new StringWriter(); transform(oXSL, aParams, oText); return new XMLHelper(oText.GetStringBuilder()); } /// /// Transforms the current DOM using the XSL to a TextWriter /// /// The XSL for the transform /// String Array of paramters to pass to the XSL /// Thre Textwriter to output to public void transform(String zXSL, Dictionary aParams, TextWriter oOut) { Stream oXSL = new FileStream(zXSL, FileMode.Open); transform(oXSL, aParams, oOut); } public void transform(Stream oXSL, Dictionary aParams, TextWriter oOut) { XslCompiledTransform transformer = new XslCompiledTransform(); XsltArgumentList args = new XsltArgumentList(); foreach (string key in aParams.Keys) { args.AddParam(key, "", aParams[key]); } //Having to specify settings for the load, due to embedded script usage... XsltSettings xsltSettings = new XsltSettings(true, true); XmlUrlResolver xmlResolver = new XmlUrlResolver(); XmlReader reader = XmlReader.Create(oXSL); transformer.Load(reader, xsltSettings, xmlResolver); //transformer.Load(oXSL, ); if (omNode.ParentNode == omNode.OwnerDocument) transformer.Transform(omNode.OwnerDocument, args, oOut); else transformer.Transform(omNode, args, oOut); } /// /// Transforms the current DOM using the XSL and returns an XMLHelper DOM /// /// The XSL for the transform /// String Array of paramters to pass to the XSL /// XMLHelper DOM with the result of the transform public XMLHelper transform(String zXSL, Dictionary aParams) { //try //{ StringWriter oText = new StringWriter(); transform(zXSL, aParams, oText); return new XMLHelper(oText.GetStringBuilder()); //} //catch (Exception ex) //{ // System.Console.WriteLine(ex.Message); // return null; //} } #endregion } }