实现客户端的DataSet

<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>

//////////////////////////////////////////////////////////
// 实现一个客户端的DataSet
//////////////////////////////////////////////////////////

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");

    // minOccurs默认为1
    if (minOccurs == null)
        minOccurs = 1;
    else
        minOccurs = new Number(minOccurs);
    

    // 如果该列允许空值或请求值为空就去掉节点
    if (vValue == null && minOccurs == 0) {
        if (oNode != null)
            oNode.parentNode.removeChild(oNode);
        return;        
    }

    // 如果以前没有设置值则添加值
    if (oNode == null) {
        var colname = oSchemaNode.getAttribute("name");
        oNode = this.XmlNode.ownerDocument.createElement(colname);
        oNode.text = vValue;
        this.XmlNode.appendChild(oNode);
        return;
    }
    
    // 如果该列已存在值则只有在值不同时才更改
    var curValue = oNode.text;
    if (curValue != vValue.toString())
    {
        if (this.XmlNode.getAttribute("diffgr:hasChanges") != "inserted") {
            // 备份原始值
            var oDiffGramBefore = this.DataTable.DataSet.XmlData.documentElement.selectSingleNode("diffgr:before");
            if (oDiffGramBefore == null) {
                oDiffGramBefore = this.XmlNode.ownerDocument.createNode(1, "diffgr:before", "urn:schemas-microsoft-com:xml-diffgram-v1");
                this.XmlNode.ownerDocument.documentElement.appendChild(oDiffGramBefore);
            }
            
            var path = this.DataTable.TableName + "[@diffgr:id='" + this.XmlNode.getAttribute("diffgr:id") + "']";
            var oOriginalRow = oDiffGramBefore.selectSingleNode(path);
            if (oOriginalRow == null) {
                // 拷贝原始行
                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.documentElement.selectSingleNode("diffgr:before");
    if (oDiffGramBefore == null) {
        oDiffGramBefore = this.XmlNode.ownerDocument.createNode(1, "diffgr:before", "urn:schemas-microsoft-com:xml-diffgram-v1");
        this.XmlNode.ownerDocument.documentElement.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.documentElement.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.document.createElement("DIV").uniqueID;
}

//////////////////////////////////////////////////////////
// Public Methods
//////////////////////////////////////////////////////////

function GetTable(vIndex)
{
    var oNodes;
    var tableName = "";
    switch (typeof(vIndex))
    {
        case "string":
            // 返回行
            tableName = vIndex;
            oNodes = XmlData.documentElement.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()
{
    // 删除节点
    var beforeNode = this.XmlData.documentElement.selectSingleNode("diffgr:before");
    
    if (beforeNode) {
        this.XmlData.documentElement.removeChild(beforeNode);
    }
        
    // 改变diffgr:hasChanges属性
    var hasChangesAttributes = XmlData.selectNodes("//@diffgr:hasChanges");
    while (hasChangesAttributes.peekNode() != null) {
        hasChangesAttributes.removeNext();
    }
}

function RejectChanges()
{
    // 删除数据
    var dataSetNode = this.XmlData.documentElement.selectSingleNode(this.Name);
    var beforeNodes = this.XmlData.documentElement.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);
            
    }

    // 删除节点
    var beforeNode = this.XmlData.documentElement.selectSingleNode("diffgr:before");
    this.XmlData.documentElement.removeChild(beforeNode);
}

function GetChanges()
{
    var ds = new ActiveXObject("Microsoft.XMLDOM");
    ds.async = false;
    ds.loadXML('<DataSet/>');

    var schemaNode = XmlSchema.documentElement.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.documentElement.selectNodes(Name + '/*[@diffgr:hasChanges]');
    while (changedNodes.peekNode() != null) {
        var changedNode = changedNodes.nextNode();
        dataNode.appendChild(changedNode.cloneNode(true));
    }
    diffNode.appendChild(dataNode);
        
    var beforeNode = XmlData.documentElement.selectSingleNode("diffgr:before");
    if (beforeNode) {


        diffNode.appendChild(beforeNode.cloneNode(true));
    }
    
    // 合并schema和数据
    ds.documentElement.appendChild(schemaNode);
    ds.documentElement.appendChild(diffNode);

    return ds.documentElement;
}

function ReadXml(doc)
{
    ReadXmlSchema(doc);

    var oDiffGram = doc.selectSingleNode("diffgr:diffgram");
    if (oDiffGram != null) {
        XmlData    = new ActiveXObject("Microsoft.XMLDOM");
        XmlData.documentElement    = oDiffGram;
    }
}

function ReadXmlSchema(doc)
{
    XmlData = null;
    
    // 得到Schema
    var oSchema = doc.selectSingleNode("xsd:schema");
    if (oSchema != null)
    {
        XmlSchema            = new ActiveXObject("Microsoft.XMLDOM");
        XmlSchema.documentElement    = oSchema;
        Name                = oSchema.selectSingleNode('xsd:element[@msdata:IsDataSet="true"]').getAttribute("name")
        Namespace            = oSchema.getAttribute("targetNamespace");
    }
}
posted @ 2008-01-19 10:21  疾行者  阅读(250)  评论(0编辑  收藏  举报