| 网站镜像:电信 网通 | 加入收藏 | 设为首页

实现一个客户端的DataSet-----ClientDataSet.htc

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