欢迎您来到 数字平台。 您尚未登录。[登录] [注册新用户]
当前位置: 论坛首页 / 栏目 产品与服务 / 文章 659

点击:38093[回复顶层] [树状] [详细]
[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 1 楼
文章id: 659
神奇的脚本 (一)

作者: xietao


dp2图书馆集成系统的dp2circulation,是这个系统的前端模块,它实现了图书馆的全部内部业务。

dp2circulation的“种册窗”,以书目数据为中心,管理一条书目记录和下属的册记录、订购记录、期记录、评注记录,还有对象资源。这是编目员最频繁使用的软件界面,其他业务环节的图书馆工作人员也会用到这个界面。

在数据库内核中,可以为每个书目数据库创建和维护一个独特的dp2circulation_marc_autogen.cs脚本文件。哦,忘了说了,这个脚本文件还会有一个配套的名为dp2circulation_marc_autogen.cs.ref的XML格式文件,用来配置上面那个文件的链接DLL信息。

dp2circulation_marc_autogen.cs文件是一个C#语言的程序文件,或者从它处于二次开发的地位那么我们习惯把它称为“脚本文件”。脚本的意思是说它比较简练地编程实现了用户希望定制的那些功能。简练,是由于dp2circulation.exe这个宿主程序具有很多很多好用的功能,只需要简单调用即可。

dp2circulation_marc_autogen.cs文件实现了种册窗中大名鼎鼎的Ctrl+A功能。我们知道,在种册窗的MARC编辑器或者“册”属性页触发Ctrl+A,会出现一个功能列表的对话框,可以选择里面的功能执行,通常都是些创建MARC数据字段,便于编目员加工维护MARC数据的实用功能。

这篇文字,并不打算全面介绍dp2circulation_marc_autogen.cs这个脚本文件的全部东西,而只是挑选其中一些有趣的,或者说神奇的功能来加以介绍,以求引起读者的兴趣。如果可能,将来我们可以展开来讨论这个对于编目员意义重大的二次开发技术热点话题。

您现在大概已经明白,后面的文字探讨,需要您具备一定的C#编程知识。当然,既然是脚本程序,并不需要精通C#编程,就能看个大概。只要您能了解它大概能做些啥,有什么技术特点,我这篇文字就算没有白写。说到“精通”C#编程,不好意思,我本人自觉算不得精通呢 --- 不过好歹我还是把那些功能都实现了。

好,闲话少说,让我们开始这趟技术旅程。



发表时间: 2011-08-11 15:34:50



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 2 楼
文章id: 660
运行条件

作者: xietao


为了使用这篇文字里列出的神奇脚本代码,您需要安装最新的dp2circulation V2版本。这是几个月前才推出的最新版本。为了能使用dp2circulation V2版本,您还需要配套的dp2library服务器V2版本,而后者又继续要求配套的dp2kernel服务器V2版本。除了dp2circulation,这两个服务器模块恐怕只能是贵馆的系统管理员才能有权将他们升级到V2版本。

这里也提醒一下,dp2circulation的V1版本没有办法自动升级到V2版本。需要您专门安装dp2circulation V2版本。V2版本和V1版本是独立的,互相不干涉。您初次安装好dp2circulation V2版本后,还需要进行少量参数配置,例如服务器地址什么的。另外全部统计二次开发模块都需要自行下载安装。



发表时间: 2011-08-11 15:40:24



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 3 楼
文章id: 661
新的加拼音功能

作者: xietao


请启动dp2manager模块,打开编辑您关注的一个书目库的下属的dp2circulation_marc_autogen.cs脚本文件。

由于历史的原因,这个脚本文件中的MyHost类,可以从两个基类中派生。现在推荐用DetailHost类。以前那个类我就不讲了,虽然现在也兼容它。请检查您打开的脚本文件中的class定义语句。

*** 准备工作

在我写这篇文章以前,脚本代码中的MyHost类是凭借自己写出来加拼音的功能,而没有借助基类DetailHost的功能。为了体验最新的效果,您需要先删除里面的下列两个函数代码:

void AddPinyin()

{

...

}

int GetPinyinCfgLine( string strFieldName, out string strFrom, out string strTo)

{

...

}

要删除的代码比较长,我在这里就不全部列出了,上面省略号代表了没有列出的部分。

另外请删除MyHost类内前部变量定义部分的下述代码:

string [] cfgFields = new string {

...

};

*** 体验新的加拼音代码

在脚本文件中适当位置加入新的AddPinyin()函数,代码如下:

 void AddPinyin()
 {
  AddPinyin(this.PinyinCfgXml);
 }

然后在MyHost内前部变量定义部分增加下述代码: 

 string PinyinCfgXml = "<root>"
  + "<item name='200' from='a' to='9' />"
  + "<item name='701' indicator='@[^A].' from='a' to='9' />"
  + "<item name='711' from='a' to='9' />"
  + "<item name='702' indicator='@[^A].' from='a' to='9' />"
  + "<item name='712' from='a' to='9' />"
  + "</root>"; 

由于以前本来在Main()函数内就有AddPinyin()函数的入口,那么到此为止代码就修改好了,保存它。

启动dp2circulation,装入一条MARC记录到种册窗,在MARC编辑器中按下Ctrl+A,选择“加拼音”功能,就能体验到新的加拼音功能了。

这个加拼音功能感觉起来和以前的没有什么不同。当然,除了选择多音字的对话框发现了点外观变化 --- 这是最近的新修改,和二次开发脚本倒是无关。

后面我会逐步展开说明这段加拼音的代码的好处。



发表时间: 2011-08-11 15:50:42
最后修改时间: 2011-08-11 22:39:52



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 4 楼
文章id: 662
删除全部拼音子字段的功能和代码

作者: xietao


以前dp2circulation可没有给用户提供过什么“删除全部拼音子字段”的代码吧。

如果这样的代码存在,恐怕也是藏在我的那个宝贝代码箱子里,没有拿出来给过用户。

很多用户可能有过这样的经历,想先删除数据中全部已有的拼音子字段再加拼音子字段,或者说,就删除但是不加。这是一个很实在的需求。如果要手动一个一个去删除拼音子字段那该多麻烦啊。

有人可能会说:难道加拼音的功能不是自动替换了旧的拼音子字段么?

是的。但是且慢,在历史上比较旧的CNMARC数据,曾经采用200$a创建拼音子字段$A这样的方法,而dp2circulation中的这个加拼音的功能,是按照200$a创建拼音子字段$9的规则,也就是说,即便替换也是替换了$9,不会去主动删除字段中的$A等。

看看,这个“删除全部拼音子字段”的功能还是有必要存在吧?并且最好能删除以前那个规则下的全部拼音子字段。

下面我就介绍一段这样的代码。

还是要在dp2manager中打开特定书目库的dp2circulation_marc_autogen.cs脚本文件。

为了能删除旧规则下的拼音子字段,需要在MyHost类里面前部变量定义的位置,增加一段下述代码:

 string OldPinyinCfgXml = "<root>"
  + "<item name='200' from='a' to='A' />"
  + "<item name='200' from='e' to='E' />"
  + "<item name='200' from='f' to='F' />"

  + "<item name='701' indicator='@[^A].' from='a' to='A' />"
  + "<item name='711' from='a' to='A' />"
  + "<item name='702' indicator='@[^A].' from='a' to='A' />"
  + "<item name='712' from='a' to='A' />"
  + "</root>";

然后,在Main()函数内增加一段代码,以创建新的功能入口:

            // 删除拼音
            actions.NewItem("删除拼音", "删除全部拼音子字段", "RemovePinyin", false);

然后,在MyHost类中适当位置增加一个RemovePinyin()函数的代码:

 void RemovePinyin()
 {
  RemovePinyin(this.PinyinCfgXml);
  RemovePinyin(this.OldPinyinCfgXml);
 }

好,代码修改就告结束。保存它。

启动dp2circulation,在种册窗里面用Ctrl+A打开功能对话框,选择“删除拼音”功能执行。

~~~

从上面的代码我们可以看出,MyHost类的RemovePinyin()函数,实际上内部调用了两次DetailHost类里面的RemovePinyin(string strCfgXml)函数。第一次调用是为了删除新规则下的全部拼音子字段,第二次调用是为了删除老规则下的全部拼音子字段。

~~~

思考题:

1) 如果仅仅要删除新规则下的全部拼音子字段,上面的代码该如何改写呢?

2) 如果想在MyHost类的RemovePinyin()函数中只调用一次DetailHost类里面的RemovePinyin(string strCfgXml)函数,就达到删除新老规则下的全部拼音子字段的效果,上面的代码又该如何改造呢?

~~~

相信如果您完成了上述思考题,就会觉得这些代码逐渐脱离了平淡无奇,开始有些“神奇”的意思了吧。对,它是柔韧的,可以像橡皮泥一样地捏来捏去。并且,它还是不失“脚本”的特性:依然简洁。



发表时间: 2011-08-11 16:14:26
最后修改时间: 2011-08-11 22:40:53



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 5 楼
文章id: 663
老的代码实现不了老规则加拼音

作者: xietao


在我写这篇文字的时候,或者说在稍早一点对dp2circulation加拼音脚本相关功能进行改造的时候,我发现一个问题:

老的拼音功能相关代码,就是这系列文章一上来要求您删除的那些老代码,实现不了老的加拼音子字段规则。就是指200$a内汉字创建拼音子字段$A,$f内汉字创建拼音子字段$F,...,那个老规则。

问题出在那个获取拼音配置信息的函数GetPinyinCfgLine()和配套的构思上面。当匹配200字段的时候,总是取出200字段的第一个子字段$a的信息,无法取出同一字段的其他子字段的信息。

假如我们这样配置:

string[] cfgFields = new string [] {

"200(a-A)",

"200(f-F)",

...

}

那么,如果我们真的验证一下,会发现第二行配置"200(f-F)"永远不可能被取出来。

这就是老代码的缺点了。幸好,新的取拼音规则,为每个字段只取一个子字段的拼音,掩盖了这个缺点。

但是要编写删除老规则下拼音子字段的功能的时候,这个问题就会暴露出来。或者,如果您偏偏要写一个按照老规则加拼音子字段的功能,也会暴露出这个问题。

~~~

好了说到这里,假如您要写一个老规则的加拼音功能,代码什么样子呢?

首先需要在Main()函数里面适当位置加一个功能入口:

            // 老规则加拼音
            actions.NewItem("老规则加拼音", "按照老规则来加拼音", "OldAddPinyin", false);

然后在MyHost类中的适当位置加入一个OldAddPinyin()函数,代码如下:

 void OldAddPinyin()
 {
  AddPinyin(this.OldPinyinCfgXml);
 }

这里假定您已经按照前面的文字加入过OldPinyinCfgXml的定义。

~~~

上面这个“优点”,我们拿着放大镜来看,是不是可以算是给“神奇”加点分呢?



发表时间: 2011-08-11 16:27:13
最后修改时间: 2011-08-11 16:28:14



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 6 楼
文章id: 664
选择多音字的缓存

作者: xietao


和我们的脚本话题有关,我介绍一下dp2circulation V2中,对加拼音功能选择多音字情况下的缓存功能。

前文介绍的最新加拼音代码,它已经具备了一个功能,当您反复为一条书目记录加拼音的时候,以前选择的多音字,那些选择,会被缓存起来,记忆到书目记录的某个位置,后来当需要选择多音字的时候,程序就自动探寻是不是有以前的缓存符合要求,如果找到缓存,就不必让操作者选择多音字了。

提醒一下,dp2系统里面的书目记录本质上是用XML格式存储的。上述拼音选择信息,您是看不到它在MARC记录中的哪里存在的,它是以XML格式存储在MARC信息以外。当然,MARC信息本质上也是最后转化为XML格式存储的。两类信息虽然同在一条书目记录中,但是互不干扰。

也就是说如果您用ISO2709格式备份出书目记录,然后摧毁书目库重建,然后重新导入这些书目记录从ISO2709文件中,那么,上述拼音选择的缓存信息就被丢失了。因为MARC格式文件无法保存那些缓存的信息。

而如果您用XML格式来备份书目记录,则可以保留拼音选择的缓存信息。

~~~

选择拼音的阶段,有了缓存,操作起来省心了,这是好事。

但是,假如第一次选择多音字的时候,明明当时选错了,后来想要重新执行一次Ctrl+A加拼音的功能,程序却固执地用以前缓存的错误选择,而不给操作者重新选择的机会,这如何是好?

先说一个笨办法:将相关的汉字子字段内容随意增加一个汉字,然后重新加拼音。这时候,由于汉字内容发生了变化,缓存虽然依然存在,但是匹配不上了,就不起作用了,于是就出现了选择多音字的对话框,可以选择了。然后对相关汉字子字段内容和依据它创建的拼音子字段内容手工稍作修改即可。

下面给出一段脚本代码,可以实现清除当前记录现有拼音选择缓存信息的功能。

在Main()函数内适当位置增加一个功能入口:

            // 清除拼音缓存
            actions.NewItem("清除拼音缓存", "清除存储的以前选择过的汉字和拼音对照关系", "ClearPinyinCache", false);

然后在MyHost类中适当位置,增加函数ClearPinyinCache()的代码:

 void ClearPinyinCache()
 {
  this.DetailForm.SetSelectedPinyin(null);
 }

保存代码。然后在dp2circulation的种册窗中试验执行一下吧。

~~~

其实,为何不在种册窗的工具条上增加一个正经八百的功能按钮“清除拼音缓存”呢?

是的。常用功能需要这样考虑。

dp2circulation这个程序,魅力就在于无论是否常用的功能,都有二次开发的功能接口,能被脚本代码调用。它简直是为二次开发而生的。这些具体的功能本来就有用,组合起来可以发挥更大的作用。



发表时间: 2011-08-11 16:44:19



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 7 楼
文章id: 665
批加拼音!

作者: xietao


下面,我们来点刺激的:为整个一个书目库的全部书目记录自动加拼音,怎么样?

其实,“自动”加拼音有点言过其实。选择多音字的操作程序还是无法代劳。最多是程序自动循环,避免操作者不停地按“下一记录”按钮手忙脚乱。但这也很有意义啊。

还是在dp2manager中打开编辑相关书目库的dp2circulation_marc_autogen.cs脚本文件。

在Main()函数中适当位置增加一个功能入口:


            // 批加拼音
            actions.NewItem("批加拼音", "为当前记录以及同库的其他后方记录重新加拼音", "BatchAddPinyin", false);

在MyHost类的适当位置增加一个函数BatchAddPinyin()的代码:

    void BatchAddPinyin()
    {
        int nRet = 0;
        Stop stop = new DigitalPlatform.Stop();
        stop.Register(this.DetailForm.MainForm.stopManager, true); // 和容器关联
        stop.Style = StopStyle.EnableHalfStop;
        stop.BeginLoop();

        try
        {

            for (; ; )
            {
                Application.DoEvents();
                if (stop.State != 0)
                    break;
                nRet = AddPinyin(this.PinyinCfgXml);
                if (nRet == -1)
                    break;
                nRet = this.DetailForm.DoSaveAll();
                if (nRet == -1)
                    break;
                nRet = this.DetailForm.SafeLoadRecord(this.DetailForm.BiblioRecPath, "next");
                if (nRet <= 0)
                    break;
            }

        }
        finally
        {
            stop.EndLoop();
            stop.Unregister();
        }

    }

代码修改完毕。保存它。然后去试验一下吧。

这个功能是从当前记录位置,顺次处理同一书目库的ID号更大的后面的记录。直到操作者在主窗口的工具条上按停止按钮,或者遇到数据库的最后一条记录被处理完。

代码中的Stop类对象,是用来表达主窗口工具条上的停止按钮的。Stop类对象可以堆叠,多重循环可以堆叠多次。这里就不展开介绍了。

除了为了循环和停止而书写的代码外,实际上加拼音和保存记录的代码都非常简单明了。



发表时间: 2011-08-11 16:55:24
最后修改时间: 2011-08-11 16:55:58



[回复留言] [回复(需要先登录)] [引用(需要先登录)]普通文章第 8 楼
文章id: 666
批删除拼音

作者: xietao


有了前面的批加拼音,批删除拼音就不难想象了。

在Main()函数中适当位置增加一个功能入口:

            // 批删除拼音
            actions.NewItem("批删除拼音", "为当前记录以及同库的其他后方记录删除拼音", "BatchRemovePinyin", false);

然后在MyHost类的适当位置增加BatchRemovePinyin()函数的代码:

    void BatchRemovePinyin()
    {
        int nRet = 0;
        Stop stop = new DigitalPlatform.Stop();
        stop.Register(this.DetailForm.MainForm.stopManager, true); // 和容器关联
        stop.Style = StopStyle.EnableHalfStop;
        stop.BeginLoop();

        try
        {

            for (; ; )
            {
                Application.DoEvents();
                if (stop.State != 0)
                    break;

                RemovePinyin(this.PinyinCfgXml);
                RemovePinyin(this.OldPinyinCfgXml);

                nRet = this.DetailForm.DoSaveAll();
                if (nRet == -1)
                    break;
                nRet = this.DetailForm.SafeLoadRecord(this.DetailForm.BiblioRecPath, "next");
                if (nRet <= 0)
                    break;
            }

        }
        finally
        {
            stop.EndLoop();
            stop.Unregister();
        }

    }

代码修改完毕。保存它。试验一下吧。

思考题:

要是我想从当前记录开始,向ID号更小的方向去继续处理循环呢?

艾,还是把答案公布了吧。

上面代码中有一行:

                nRet = this.DetailForm.SafeLoadRecord(this.DetailForm.BiblioRecPath, "next");

把"next"改为"prev"就可以了。

~~~

自从学会了如何循环处理多条记录,恐怕不少人以后想象力就是一发不可收了吧!



发表时间: 2011-08-11 17:01:54



页 1 / 1
 

在线用户
(无) 
当前栏目在线用户数 0, 总在线用户数 0