using System.Collections.Specialized;
using System.Data.Common;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Xsl;
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 DbConnection _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
{
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
}
}