首页 > 其他 > 详细

从零开始的文档对象模型(不断更新)

时间:2020-05-28 22:13:56      阅读:53      评论:0      收藏:0      [点我收藏+]

从字符串说起

假设现在有几条数据,是以记事本文档的形式交到我们的手中

姓名:涂白竹  性别:女  年龄:15  班级:1班

姓名:江夜梅  性别:女  年龄:16  班级:1班

姓名:奉轩      性别:男  年龄:15  班级:1班

我们的任务是将他们录入到数据库中,并且这几个学生都要转到2班。怎么做?假设数据表已经建立好了。

第一思路:读取文档,通过换行符分割这几行数据,再将每条子串的倒数第二个字符替换为2.

代码如下:

StreamReader sr = new StreamReader("DOM演示\\学生数据.txt",Encoding.Default);
string s = sr.ReadToEnd();
sr.Close();
string[] students = s.Split(new String[]{"\n"},StringSplitOptions.None);
foreach (string item in students)
{
    string temp = item.Replace(item.Substring(item.IndexOf("班级:") + 3, item.Length - item.IndexOf("班级:") - 3), "2班");
    Console.WriteLine(temp);
}    

运行结果:

技术分享图片

可以说非常麻烦。而且如果要改的是年龄呢?如果只是改(江夜梅)的年龄呢?那又要改代码了。每次调整需求就要改代码。

为了提高代码复用率,不如写成函数。

按照要求,是改任意一个人的任意属性。问题在于任何属性值的长度是不固定的。没办法像前面一样截取后2位更改。

文档规范化

思考一下XML或HTML是怎么做的。在值的前后加标记。

于是我们也仿照HTML制定一个规范:

姓名,必须在<name></name>中间

性别,必须在<sex></sex>中间

年龄,必须在<sex></sex>中间

班级,必须在<sex></sex>中间

现在来改造文档,用这种格式写

<name>涂白竹</name><sex></sex><age>15</age><class>1班</class>
<name>江夜梅</name><sex></sex><age>16</age><class>1班</class>
<name>奉轩</name><sex></sex><age>15</age><class>1班</class>

找到标签,和更改内容

现在再来改造代码:

public void update(string propertyName,string propertyValue)
        {
            StreamReader sr = new StreamReader("DOM演示\\规范化学生数据.txt", Encoding.Default);
            string s = sr.ReadToEnd();
            sr.Close();

            string[] students = s.Split(new String[] { "\n" }, StringSplitOptions.None);
            foreach (string item in students)
            {
                int startIndex = item.IndexOf("<" + propertyName + ">") + propertyName.Length + 2;
                int endIndex = item.IndexOf("</" + propertyName + ">");
                int valueLength = endIndex - startIndex;
                string temp = item.Replace(item.Substring(item.IndexOf("<" + propertyName + ">") + propertyName.Length + 2, valueLength), propertyValue);
                Console.WriteLine(temp);
            }
        }

调用:update("age", "20");
           //update("class", "2班");

技术分享图片

现在的问题是在显示时如何去掉标签?

不如专门写一个函数,去掉字符串”<“和">"之间的字符。然后在update()中每次输出时调用。

函数:获得指定串的所有位置

引用自:https://blog.csdn.net/iteye_19871/article/details/81495660

public int[]GetSubStrCountInStr(String str,String substr,int StartPos)
        {
            int foundPos=-1;
            int count=0;
            List<int> foundItems=new List<int>();

            do
            {
                foundPos=str.IndexOf(substr,StartPos);
                if(foundPos>-1)
                {
                    StartPos=foundPos+1;
                    count++;
                    foundItems.Add(foundPos);
                }
            }while(foundPos>-1&&StartPos<str.Length);
            return((int[])foundItems.ToArray());
        }

调用这个函数完成对标记的去除,其实是反过来,只取值

public string remove(string student)
        {
            int[] left = GetSubStrCountInStr(student, "<", 0);
            int[] right = GetSubStrCountInStr(student, ">", 0);
            string newString = "";
            for (int i=0,j=1;i<left.Length-1;i++,j++)
            {
                newString += student.Substring(right[i]+1, left[j] - right[i]-1)+"\t";
            }
            return newString;
        }

然后在update()中调用

public void update(string propertyName,string propertyValue)
        {
            StreamReader sr = new StreamReader("DOM演示\\规范化学生数据.txt", Encoding.Default);
            string s = sr.ReadToEnd();
            sr.Close();

            string[] students = s.Split(new String[] { "\n" }, StringSplitOptions.None);
            foreach (string item in students)
            {
                int startIndex = item.IndexOf("<" + propertyName + ">") + propertyName.Length + 2;
                int endIndex = item.IndexOf("</" + propertyName + ">");
                int valueLength = endIndex - startIndex;
                string temp = item.Replace(item.Substring(item.IndexOf("<" + propertyName + ">") + propertyName.Length + 2, valueLength), propertyValue);
                //string newString = remove(temp);<---这里调用
                Console.WriteLine(newString);
            }
        }

现在就能实现对任意属性的修改了。

技术分享图片

虽然修改成功了,但并没有指定特定的个人。当然,可以继续修改这个remove()函数。

我们的操作一共有查看(select),新增(insert),删除(delete),修改(update)。也就是说,每个操作都要写一个函数。

 为了方便起见,我们把他们组织成一个类。但是组织成类。。。

现在要考虑的是学生的属性个数并不确定,可能会改变。

不如就像XML做的那样,把这些属性都看作节点,学生就是这些属性节点的父节点。这样就可以随意增添子节点(属性)。

那采用递归的方式比较好,采用设计模式里面的组合模式。假设类名叫Node,里面包含两个字段nodeName,txtValue外加一个集合child

现在可以再次改进文档

 原来的的格式不足之处在于是通过换行符“\n”来区分不同记录的,当两条记录处于同一行就会出问题。而且这样不利于体现结构。

现在改成就像XML一样

<students>
<student>
    <name>涂白竹</name>
    <sex></sex>
    <age>15</age>
    <class>1班</class>
</student>
<student>
    <name>江夜梅</name>
    <sex></sex>
    <age>16</age>
    <class>1班</class>
    </student>
<student>
    <name>奉轩</name>
    <sex></sex>
    <age>15</age>
    <class>1班</class>
</student>
</students>

这样,从根节点开始,每个子节点<student>就是一条记录。

现在就可以利用Node来在内存中加载数据了。

利用有限状态自动机来读取文档,并在这个过程中保存数据,用于在正确结束后生成文档对象。

技术分享图片

接下来就是实现了。待更新。。。

 

 

从零开始的文档对象模型(不断更新)

原文:https://www.cnblogs.com/ggtc/p/12982302.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!