<PUBLIC: COMPONENT lightWeight = "true">
<PUBLIC: PROPERTY name = "Name" value = "DataSet"/>
<PUBLIC: PROPERTY name = "Namespace" value = "http://tempuri.org"/>
<PUBLIC: PROPERTY name = "XmlData"/>
<PUBLIC: PROPERTY name = "XmlSchema"/>
<PUBLIC: METHOD name = "ReadXml"/>
<PUBLIC: METHOD name = "ReadXmlSchema"/>
<PUBLIC: METHOD name = "GetTable"/>
<PUBLIC: METHOD name = "AcceptChanges"/>
<PUBLIC: METHOD name = "RejectChanges"/>
<PUBLIC: METHOD name = "GetChanges"/>
<PUBLIC: EVENT name = "ondatachanged" id = "datachanged"/>
</PUBLIC: COMPONENT>
<SCRIPT>
//////////////////////////////////////// //////////////////
// Implement the DataSet of a client
//////////////////////////////////////// //////////////////
Function DataRow (dt, oNode)
{
This. DataTable = dt;
This. XmlNode = oNode;
This. GetValue = DataRow_GetValue;
This. SetValue = DataRow_SetValue;
This. Delete = DataRow_Delete;
}
Function DataRow_GetValue (vIndex)
{
Var oNode;
Switch (typeof (vIndex ))
{
Case "string ":
ONode = this. XmlNode. selectSingleNode (vIndex );
Break;
Default:
Throw "You must index into a DataRow using the string name .";
}
If (oNode! = Null)
{
Return oNode. text;
}
Return null;
}
Function DataRow_SetValue (vIndex, vValue)
{
Var oNode;
Var oSchemaNode;
Switch (typeof (vIndex ))
{
Case "string ":
ONode = this. XmlNode. selectSingleNode (vIndex );
OSchemaNode = this. DataTable. SchemaNode. selectSingleNode ('xsd: complexType/xsd: sequence/xsd: element [@ name = "'+ vIndex +'"] ');
If (oSchemaNode = null)
Throw "Invaid column index:" + vIndex;
Break;
Default:
// ONode = this. XmlNode. childNodes [vIndex];
Throw "Invaid column index:" + vIndex;
}
Var minOccurs = oSchemaNode. getAttribute ("minOccurs ");
// The default value of minOccurs is 1.
If (minOccurs = null)
MinOccurs = 1;
Else
MinOccurs = new Number (minOccurs );
// If the column allows null values or the request value is null, remove the node.
If (vValue = null & minOccurs = 0 ){
If (oNode! = Null)
ONode. parentNode. removeChild (oNode );
Return;
}
// Add a value if no value is set before
If (oNode = null ){
Var colname = oSchemaNode. getAttribute ("name ");
ONode = this. XmlNode. ownerDocument. createElement (colname );
ONode. text = vValue;
This. XmlNode. appendChild (oNode );
Return;
}
// If the column already exists, the value is changed only when the value is different.
Var curValue = oNode. text;
If (curValue! = VValue. toString ())
{
If (this. XmlNode. getAttribute ("diffgr: hasChanges ")! = "Inserted "){
// Original backup Value
Var oDiffGramBefore = this.DataTable.DataSet.XmlData.doc umentElement. selectSingleNode ("diffgr: before ");
If (oDiffGramBefore = null ){
ODiffGramBefore = this. XmlNode. ownerDocument. createNode (1, "diffgr: before", "urn: schemas-microsoft-com: xml-diffgram-v1 ");
This.XmlNode.ownerDocument.doc umentElement. appendChild (oDiffGramBefore );
}
Var path = this. DataTable. TableName + "[@ diffgr: id = '" + this. XmlNode. getAttribute ("diffgr: id") + "']";
Var oOriginalRow = oDiffGramBefore. selectSingleNode (path );
If (oOriginalRow = null ){
// Copy the original row
ODiffGramBefore. appendChild (this. XmlNode. cloneNode (true ));
}
This. XmlNode. setAttribute ("diffgr: hasChanges", "modified ");
}
ONode. text = new String (vValue );
}
}
Function DataRow_Delete ()
{
Var oDiffGramBefore = this.DataTable.DataSet.XmlData.doc umentElement. selectSingleNode ("diffgr: before ");
If (oDiffGramBefore = null ){
ODiffGramBefore = this. XmlNode. ownerDocument. createNode (1, "diffgr: before", "urn: schemas-microsoft-com: xml-diffgram-v1 ");
This.XmlNode.ownerDocument.doc umentElement. appendChild (oDiffGramBefore );
}
Var oBeforeNode = oDiffGramBefore. selectSingleNode (this. xmlNode. nodeName + "[@ diffgr: id = '" + this. xmlNode. getAttribute ("diffgr: id") + "']");
If (oBeforeNode = null ){
// This. XmlNode. setAttribute ("xmlns", this. DataTable. DataSet. Namespace );
ODiffGramBefore. appendChild (this. XmlNode );
This. XmlNode. setAttribute ("xmlns", this. DataTable. DataSet. Namespace );
}
Else {
This. XmlNode. parentNode. removeChild (this. XmlNode );
}
This. XmlNode = null;
}
Function DataTable (ds, name, oNodes)
{
This. XmlNodes = oNodes;
This. DataSet = ds;
This. TableName = name;
This. GetRowCount = DataTable_GetRowCount;
This. GetRow = DataTable_GetRow;
This. AddRow = DataTable_AddRow;
This. FindRow = DataTable_FindRow;
This. SchemaNode = ds. XmlSchema. selectSingleNode ('// xsd: element [@ name = "' + name + '"]');
If (this. SchemaNode = null ){
Throw name + "table not found in DataSet schema .";
}
}
Function DataTable_GetRowCount ()
{
Return this. XmlNodes. length;
}
Function DataTable_GetRow (I)
{
Return new DataRow (this, this. XmlNodes [I]);
}
Function DataTable_AddRow ()
{
Var oRow = this. DataSet. XmlData. createElement (this. TableName );
ORow. setAttribute ("diffgr: id", createID ());
// ORow. setAttribute ("msdata: rowOrder", this. GetRowCount ());
ORow. setAttribute ("diffgr: hasChanges", "inserted ");
// Add the column elements with their default values to the new empty row
Var columns = this. SchemaNode. selectNodes ("xsd: complexType/xsd: sequence/xsd: element ");
For (var I = 0; I <columns. length; I ++)
{
Var col = columns [I];
Var minOccurs = col. getAttribute ("minOccurs ");
Var defaultValue = col. getAttribute ("default ");
If (minOccurs = null)
MinOccurs = 1;
Else
MinOccurs = new Number (minOccurs );
If (minOccurs> 0 | defaultValue! = Null ){
Var colname = col. getAttribute ("name ");
Var oCol = this. DataSet. XmlData. createElement (colname );
If (defaultValue! = Null)
OCol. text = new String (defaultValue );
ORow. appendChild (oCol );
}
}
Var oDataSet = this.DataSet.XmlData.doc umentElement. selectSingleNode (this. DataSet. Name );
ODataSet. appendChild (oRow );
This. XmlNodes = oDataSet. selectNodes (this. TableName );
Return new DataRow (this, oRow );
}
Function DataTable_FindRow (xpr)
{
Var oDataSet = this. DataSet. XmlData. selectNodes (this. DataSet. Name );
If (oDataSet ){
Var oRow = oDataSet. selectSingleNode (this. TableName + "[" + expr + "]");
If (oRow ){
Return new DataRow (this, oRow );
}
}
Return null;
}
//////////////////////////////////////// //////////////////
// Private Variables
//////////////////////////////////////// //////////////////
//////////////////////////////////////// //////////////////
// Private Methods
//////////////////////////////////////// //////////////////
Function createID ()
{
Return element.doc ument. createElement ("DIV"). uniqueID;
}
//////////////////////////////////////// //////////////////
// Public Methods
//////////////////////////////////////// //////////////////
Function GetTable (vIndex)
{
Var oNodes;
Var tableName = "";
Switch (typeof (vIndex ))
{
Case "string ":
// Return row
TableName = vIndex;
ONodes = XmlData.doc umentElement. selectNodes (Name + "/" + tableName );
Break;
Case "number ":
Throw "Index by position not supported .";
Break;
}
If (oNodes! = Null)
{
Return new DataTable (this, tableName, oNodes );
}
Return null;
}
Function AcceptChanges ()
{
// Delete a node
Var beforeNode = this.XmlData.doc umentElement. selectSingleNode ("diffgr: before ");
If (beforeNode ){
This.XmlData.doc umentElement. removeChild (beforeNode );
}
// Change the diffgr: hasChanges attribute
Var hasChangesAttributes = XmlData. selectNodes ("// @ diffgr: hasChanges ");
While (hasChangesAttributes. peekNode ()! = Null ){
HasChangesAttributes. removeNext ();
}
}
Function RejectChanges ()
{
// Delete data
Var dataSetNode = this.XmlData.doc umentElement. selectSingleNode (this. Name );
Var beforeNodes = this.XmlData.doc umentElement. selectNodes ("diffgr: before /*");
While (beforeNodes. peekNode ()! = Null ){
Var beforeNode = beforeNodes. nextNode ();
Var path = beforeNode. nodeName + "[@ diffgr: id = '" + beforeNode. getAttribute ("diffgr: id") + "']";
Var changedRow = dataSetNode. selectSingleNode (path );
If (changedRow! = Null)
DataSetNode. replaceChild (beforeNode, changedRow)
Else
DataSetNode. appendChild (beforeNode );
}
// Delete a node
Var beforeNode = this.XmlData.doc umentElement. selectSingleNode ("diffgr: before ");
This.XmlData.doc umentElement. removeChild (beforeNode );
}
Function GetChanges ()
{
Var ds = new ActiveXObject ("Microsoft. XMLDOM ");
Ds. async = false;
Ds. loadXML ('<DataSet/> ');
Var schemaNode = XmlSchema.doc umentElement. cloneNode (true );
Var diffNode = ds. createNode (1, "diffgr: diffgram", "urn: schemas-microsoft-com: xml-diffgram-v1 ");
DiffNode. setAttribute ("xmlns: msdata", "urn: schemas-microsoft-com: xml-msdata ");
Var dataNode = ds. createElement (Name );
DataNode. setAttribute ("xmlns", this. Namespace );
Var changedNodes = XmlData.doc umentElement. selectNodes (Name + '/* [@ diffgr: hasChanges]');
While (changedNodes. peekNode ()! = Null ){
Var changedNode = changedNodes. nextNode ();
DataNode. appendChild (changedNode. cloneNode (true ));
}
DiffNode. appendChild (dataNode );
Var beforeNode = XmlData.doc umentElement. selectSingleNode ("diffgr: before ");
If (beforeNode ){
DiffNode. appendChild (beforeNode. cloneNode (true ));
}
// Merge schema and Data
Ds.doc umentElement. appendChild (schemaNode );
Ds.doc umentElement. appendChild (diffNode );
Return ds.doc umentElement;
}
Function ReadXml (doc)
{
ReadXmlSchema (doc );
Var oDiffGram = doc. selectSingleNode ("diffgr: diffgram ");
If (oDiffGram! = Null ){
XmlData = new ActiveXObject ("Microsoft. XMLDOM ");
XmlData.doc umentElement = oDiffGram;
}
}
Function ReadXmlSchema (doc)
{
XmlData = null;
// Get Schema
Var oSchema = doc. selectSingleNode ("xsd: schema ");
If (oSchema! = Null)
{
XmlSchema = new ActiveXObject ("Microsoft. XMLDOM ");
XmlSchema.doc umentElement = oSchema;
Name = oSchema. selectSingleNode ('xsd: element [@ msdata: IsDataSet = "true"] '). getAttribute ("name ")
Namespace = oSchema. getAttribute ("targetNamespace ");
}
}